草庐IT

阿里云-对象存储OSS

码赛客1024 2023-09-13 原文

大家好,我是 码赛客1024 ,今天我们一起来学习阿里云的对象存储服务OSS。

一、介绍

阿里云对象存储OSS(Object Storage Service)是一款海量、安全、低成本、高可靠的云存储服务,提供99.9999999999%(12个9)的数据持久性,99.995%的数据可用性。多种存储类型供选择,全面优化存储成本。

简单理解就是一个云储存服务器,可以把我们的文件存储到阿里云的服务器中。

先完成阿里云账号注册,地址 https://www.aliyun.com/,完成实名制认证。

二、设置AccessKey

阿里云为了其API的访问安全考虑,设置了AccessKey的安全方案,AccessKey是我们访问阿里云 API 的密钥,具有该账户完全的权限,请您妥善保管。

我们待会要访问OSS服务,所以先把AccessKey创建好,方便后边使用。

设置方式:
① 进入账号中心,点击自己的头像,在下拉菜单中点击AccessKey管理,进入设置界面。

选择继续使用 AccessKey

② 生成AccessKey,可以看到起包含:AccessKey ID 和 AccessKey Secret 两部分。
这里注意:一旦点击确定,AccessKey的Secret就会隐藏起来,想查看的话,要通过验证码校验后才能查看,所以建议先复制一份,方便后期使用。

三、开通OSS服务

在产品中找到 对象存储OSS 服务,并开通

开通后,点击 “管理控制台” 进入OSS的页面

四、项目环境准备

4.1 创建SpringBoot项目

pom.xml依赖如下:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.6.10</version>
    <relativePath/>
</parent>
...
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!--aliyun oss依赖-->
    <dependency>
        <groupId>com.aliyun.oss</groupId>
        <artifactId>aliyun-sdk-oss</artifactId>
        <version>3.15.0</version>
    </dependency>
</dependencies>

4.2 准备页面

创建页面:resources/static/upload.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>上传文件</title>
    <script src="https://code.jquery.com/jquery-1.10.2.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.form/4.2.1/jquery.form.min.js"></script>
</head>
<body>
    <form id="fileForm" action="/upload" method="post" enctype="multipart/form-data">
        选择文件:<input type="file" name="file"> <br>
        <input type="button" value="上传" id="sub">
    </form>
    <script>
        $(function (){
            $("#sub").click(function (){
                $("#fileForm").ajaxSubmit({
                    success:function (data){
                        if(data.code == 2000){
                            let img = $("<img src="+data.url+" style='width:200px'>");
                            $("body").append(img);
                        }else if(data.code == 5000){
                            alert("文件上传失败,请联系管理员!");
                        }
                    }
                });
            });
        });
    </script>
</body>
</html>

4.3 准备controller

@RestController
public class FileController {
    @Autowired
    private IFileService fileService;
    /**
     * 上传文件
     * @param file 文件
     * @return 
     */
    @RequestMapping("/upload")
    public Map<String,Object> uploadFile(MultipartFile file){
        //调用业务层实现上传
        String url = fileService.uploadFile(file);
        Map<String,Object> map = new HashMap<>();
        if (url==null){
            map.put("code",5000);
            map.put("msg","上传失败");
            return map;
        }
        map.put("code",2000);
        map.put("msg","上传成功");
        map.put("url",url);
        return map;
    }
}

4.4 准备service

① 业务层接口

public interface IFileService {
    String uploadFile(MultipartFile file);
}

② 业务层实现类

@Service
public class FileServiceImpl implements IFileService {
  
    @Override
    public String uploadFile(MultipartFile file) {
    	//在这里使用阿里云oss完成文件上传
		return null;
	}
}

4.5 yml配置

application.yml

spring:
  servlet:
    multipart:
      enabled: true
      max-file-size: 5MB      # 上传文件单个限制

五、项目中使用OSS

5.1 Bucket介绍

Bucket翻译为水桶。官方解释:存储空间是您用于存储对象(Object)的容器,所有的对象都必须隶属于某个存储空间。

也就是:在OSS中,基于不同的业务需求,可以将不同的文件存储在不同的Bucket中(存储空间),以此做到文件的分类保存。即:Bucket就是存储空间。

① 新建Bucket

② 填写信息创建Bucket

创建完毕后,在列表中就可以看到自己创建的Bucket。

③ 在 “概览” 中可以看到新创建的Bucket信息
其中 Bucket域名 需要注意,在文件上传成功后,访问文件的路径就是:https://Bucket的域名/文件路径,我这里就是:https://msk1024.oss-cn-chengdu.aliyuncs.com/文件路径

5.2 调用API完成上传

① 查看Java API 文档

但是,这样打开,他的文档是以小窗口的形式展示,不方便查询,建议在文档中心查看API,文档中心地址:https://help.aliyun.com/,进入后依次找到:存储 -> 对象存储OSS 即可。

② 查看SDK上传示例

SDK示例 -> Java -> 上传文件 -> 简单上传 -> 上传文件流 。

官方示例如下:

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import java.io.FileInputStream;
import java.io.InputStream;

public class Demo {

    public static void main(String[] args) throws Exception {
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
        String accessKeyId = "yourAccessKeyId";
        String accessKeySecret = "yourAccessKeySecret";
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "examplebucket";
        // 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
        String objectName = "exampledir/exampleobject.txt";
        // 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
        // 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。
        String filePath= "D:\\localpath\\examplefile.txt";

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            InputStream inputStream = new FileInputStream(filePath);            
            // 创建PutObject请求。
            ossClient.putObject(bucketName, objectName, inputStream);
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}                    

③ 将上传代码整合到我们的业务层实现中

@Service
public class FileServiceImpl implements IFileService {

    //上传文件
    @Override
    public String uploadFile(MultipartFile file) {
        //地域节点地址(一定记得要和自己创建存储空间时选择的地域地址一致)
        String endpoint = "oss-cn-chengdu.aliyuncs.com";
        //存储空间名
        String bucketName = "msk1024";
        //自己的秘钥id
        String accessKeyId = "msk1024msk1024msk1024";
        //自己的秘钥值
        String accessKeySecret = "msk1024msk1024msk1024msk1024";
        //执行上传
        return alibabaSSO(file,endpoint,bucketName,accessKeyId,accessKeySecret);
    }

    /**
     * 文件上传
     * @param file         文件
     * @param endpoint     地域对应的服务器地址,例如:成都 -> https:oss-cn-chengdu.aliyuncs.com
     * @param bucketName   存储空间名字
     * @param accessKeyId      秘钥id
     * @param accessKeySecret  密码值
     * @return 返回文件的url
     */
    private String alibabaSSO(MultipartFile file,String endpoint,String bucketName,String accessKeyId,String accessKeySecret){
        //【1.设置文件在bucket中存储的路径格式为: 年/月/日/文件名】
        SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd/");
        String filePath = format.format(new Date());
        //重命名文件
        String filename = UUID.randomUUID().toString().replaceAll("-","")+file.getOriginalFilename();
        //完整路径中不能包含Bucket名称,例如:2022/10/27/sgfhiasndas8dasndask.png
        String objectName = filePath+filename;
        //【2.创建OSSClient实例】
        OSS ossClient = new OSSClientBuilder().build("https://"+endpoint, accessKeyId, accessKeySecret);
        try {
            //【3.创建PutObject请求,执行上传】
            ossClient.putObject(bucketName, objectName, file.getInputStream());
            //【4.上传成功后,拼接好文件的url并返回】
            //格式为:   https://存储空间名.地域地址/文件路径
            //我这里就是:https://msk1024.oss-cn-chengdu.aliyuncs.com/2022/10/27/sgfhiasndas8dasndask.png
            String url = "https://"+bucketName+"."+endpoint+"/"+objectName;
            return url;
        }catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } catch (IOException e){
            System.out.println("IOException:" + e.getMessage());
        }finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return null;
    }
}

5.3 结果展示

上传了3张图片

① OSS中查看上传的文件,单击文件后边的 “详情” 按钮可以查看文件详细信息

② 浏览器中效果如下
响应消息:

{
	code: 2000
	msg: "上传成功"
	url: "https://msk1024.oss-cn-chengdu.aliyuncs.com/2022/10/27/65ac690f9d4b45f396270be6bae252252.png"
}

页面效果:

完结撒花。
原创不易,一健三联哦,感谢。

有关阿里云-对象存储OSS的更多相关文章

  1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  2. ruby-on-rails - 按天对 Mongoid 对象进行分组 - 2

    在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev

  3. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  4. ruby-on-rails - 如何验证非模型(甚至非对象)字段 - 2

    我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss

  5. Ruby 写入和读取对象到文件 - 2

    好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信

  6. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  7. ruby-on-rails - 未在 Ruby 中初始化的对象 - 2

    我在Rails工作并有以下类(class):classPlayer当我运行时bundleexecrailsconsole然后尝试:a=Player.new("me",5.0,"UCLA")我回来了:=>#我不知道为什么Player对象不会在这里初始化。关于可能导致此问题的操作/解释的任何建议?谢谢,马里奥格 最佳答案 havenoideawhythePlayerobjectwouldn'tbeinitializedhere它没有初始化很简单,因为你还没有初始化它!您已经覆盖了ActiveRecord::Base初始化方法,但您没有调

  8. ruby - 如何在 Rails 4 中使用表单对象之前的验证回调? - 2

    我有一个服务模型/表及其注册表。在表单中,我几乎拥有服务的所有字段,但我想在验证服务对象之前自动设置其中一些值。示例:--服务Controller#创建Action:defcreate@service=Service.new@service_form=ServiceFormObject.new(@service)@service_form.validate(params[:service_form_object])and@service_form.saverespond_with(@service_form,location:admin_services_path)end在验证@ser

  9. ruby - 一个 YAML 对象可以引用另一个吗? - 2

    我想让一个yaml对象引用另一个,如下所示:intro:"Hello,dearuser."registration:$introThanksforregistering!new_message:$introYouhaveanewmessage!上面的语法只是它如何工作的一个例子(这也是它在thiscpanmodule中的工作方式。)我正在使用标准的ruby​​yaml解析器。这可能吗? 最佳答案 一些yaml对象确实引用了其他对象:irb>require'yaml'#=>trueirb>str="hello"#=>"hello"ir

  10. ruby - 更改 ActiveRecord 中对象的类 - 2

    假设我有一个FireNinja我的数据库中的对象,使用单表继承存储。后来才知道他真的是WaterNinja.将他更改为不同的子类的最干净的方法是什么?更好的是,我很想创建一个新的WaterNinja对象并替换旧的FireNinja在数据库中,保留ID。编辑我知道如何创建新的WaterNinja来self现有FireNinja的对象,我也知道我可以删除旧的并保存新的。我想做的是改变现有项目的类别。我是通过创建一个新对象并执行一些ActiveRecord魔法来替换行,还是通过对对象本身做一些疯狂的事情,或者甚至通过删除它并使用相同的ID重新插入来做到这一点,这是问题的一部分。

随机推荐