• SpringBoot集成阿里云OSS存储服务(普通上传、服务端签名上传)


    前言

    学习文档:

    学习视频:

    image-20221110164819639

    本博客的所有配套代码:aliyun-oss—Giteealiyun-oss—Github

    所有博客文件目录索引:博客目录索引(持续更新)

    一、初步阶段

    1.1、认识OSS服务与开通OSS服务(创建Bucket、配置用户权限以及允许跨域)

    阿里云开通OSS存储服务可见我的博客:阿里云开通OSS存储服务详细流程

    2022.11.11编辑最新流程文档:创建Bucket、配置用户权限以及允许跨域

    若是我们仅仅用来自己项目测试的话可以按照下面的来进行创建:

    image-20221110165504958

    记住要为对应的bucket设置对应的用户权限:对于创建子用户操作见我上面的文章链接跟着走一遍就行!

    image-20221110171909635

    image-20221110172640265

    配置跨域请求:

    image-20221111092944266

    image-20221111092957833


    1.2、起步demo:GetStartedSample(上传、删除案例)

    首先来到官方文档:

    image-20221110170004135

    image-20221110170902235

    代码来源:OSS Java SDK 3.13.2版本—阿里官方文档

    依赖:

    <dependency>
        <groupId>com.aliyun.ossgroupId>
        <artifactId>aliyun-sdk-ossartifactId>
        <version>3.14.0version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    代码:已调试其中的带中文注释

    package com.changlu.test.common;
    
    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.io.Writer;
    
    import com.aliyun.oss.ClientException;
    import com.aliyun.oss.OSS;
    import com.aliyun.oss.OSSClientBuilder;
    import com.aliyun.oss.OSSException;
    import com.aliyun.oss.model.*;
    
    /**
     * This sample demonstrates how to get started with basic requests to Aliyun OSS 
     * using the OSS SDK for Java.
     */
    public class GetStartedSample {
        
        private static String endpoint = "";
        private static String accessKeyId = "";
        private static String accessKeySecret = "";
    //    private static String bucketName = "pictured-bed";
        private static String bucketName = "";
        private static String key = "test/test2/";//若是目录,一定要设置/
    
        //方便之后拼接
        private static String shortEndpoint = "oss-cn-beijing.aliyuncs.com";
        
        public static void main(String[] args) throws IOException {
            /*
             * Constructs a client instance with your account for accessing OSS
             */
            OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
            
            System.out.println("Getting Started with OSS SDK for Java\n");
            
            try {
    
    //            /*
    //             * Determine whether the bucket exists 查看桶是否存在
    //             */
    //            if (!ossClient.doesBucketExist(bucketName)) {  //创建桶
    //                /*
    //                 * Create a new OSS bucket
    //                 */
    //                System.out.println("Creating bucket " + bucketName + "\n");
    //                ossClient.createBucket(bucketName);//根据当前的认证信息来进行创建Bucket桶,默认是私有
    //                CreateBucketRequest createBucketRequest= new CreateBucketRequest(bucketName);
    //                createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);//设置读写权限为公开读
    //                ossClient.createBucket(createBucketRequest);//来
    //            }
    
                /*
                 * List the buckets in your account:获取所有的桶名称
                 */
    //            System.out.println("Listing buckets");
    //
    //            ListBucketsRequest listBucketsRequest = new ListBucketsRequest();
    //            listBucketsRequest.setMaxKeys(500);
    //
    //            for (Bucket bucket : ossClient.listBuckets()) { //发起请求
    //                System.out.println(" - " + bucket.getName());
    //            }
    //            System.out.println();
    //
                /*
                 * 上传文件
                 * Upload an object to your bucket:上传对象到你的桶中
                 */
    //            System.out.println("Uploading a new object to OSS from a file\n");
    //            File file = new File("C:\\Users\\93997\\Desktop\\桌面壁纸\\1.png");
    //            String saveFilePath = key + file.getName();//拼接目标路径 + 图片名称
    //            //第一个参数为:桶的名称;第二个参数为路径+上你的文件名,如test/1.png,若是test/test2/1.png,也会给我们自动创建目录
    //            //第三个参数为:文件对象
    //            ossClient.putObject(new PutObjectRequest(bucketName,saveFilePath , file));
    //            //拼接获取公共访问地址
    //            String publicVisitPath = "http://" + bucketName + '.' +  shortEndpoint + "/" + saveFilePath;
    //            System.out.println("访问路径:" + publicVisitPath);
    //
    //            /*
    //             * 删除文件
    //             * Delete an object:删除对象
    //             */
                System.out.println("Deleting an object\n");
                File file = new File("C:\\Users\\93997\\Desktop\\桌面壁纸\\1.png");
                String saveFilePath = key + file.getName();//拼接目标路径 + 图片名称
                ossClient.deleteObject(bucketName, saveFilePath);
    
    //            /*
    //             * Determine whether an object residents in your bucket:判断对象是否存在你的桶
    //             */
    //            boolean exists = ossClient.doesObjectExist(bucketName, key);
    //            System.out.println("Does object " + bucketName + " exist? " + exists + "\n");
    //
    //            ossClient.setObjectAcl(bucketName, key, CannedAccessControlList.PublicRead);
    //            ossClient.setObjectAcl(bucketName, key, CannedAccessControlList.Default);
    //
    //            ObjectAcl objectAcl = ossClient.getObjectAcl(bucketName, key);
    //            System.out.println("ACL:" + objectAcl.getPermission().toString());
    //
    //            /*
    //             * Download an object from your bucket
    //             */
    //            System.out.println("Downloading an object");
    //            OSSObject object = ossClient.getObject(bucketName, key);
    //            System.out.println("Content-Type: "  + object.getObjectMetadata().getContentType());
    //            displayTextInputStream(object.getObjectContent());
    //
    //            /*
    //             * List objects in your bucket by prefix
    //             */
    //            System.out.println("Listing objects");
    //            ObjectListing objectListing = ossClient.listObjects(bucketName, "My");
    //            for (OSSObjectSummary objectSummary : objectListing.getObjectSummaries()) {
    //                System.out.println(" - " + objectSummary.getKey() + "  " +
    //                                   "(size = " + objectSummary.getSize() + ")");
    //            }
    //            System.out.println();
    //
    
                
            } 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 {
                /*
                 * Do not forget to shut down the client finally to release all allocated resources.
                 */
                ossClient.shutdown();
            }
        }
        
        private static File createSampleFile() throws IOException {
            File file = File.createTempFile("oss-java-sdk-", ".txt");
            file.deleteOnExit();
    
            Writer writer = new OutputStreamWriter(new FileOutputStream(file));
            writer.write("abcdefghijklmnopqrstuvwxyz\n");
            writer.write("0123456789011234567890\n");
            writer.close();
    
            return file;
        }
    
        private static void displayTextInputStream(InputStream input) throws IOException {
            BufferedReader reader = new BufferedReader(new InputStreamReader(input));
            while (true) {
                String line = reader.readLine();
                if (line == null) break;
    
                System.out.println("    " + line);
            }
            System.out.println();
            
            reader.close();
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172

    二、实战系列

    2.1、上传文件-简单上传

    配套代码:AliyunOss-SDK—GiteeAliyunOss-SDK—Github

    文档可见官网有对应不同功能的代码示例:简单上传文档

    image-20221110171128549

    测试其中的上传文件流:直接复制的上面文件流的示例代码,然后去修改一下配置信息即可

    package com.changlu;
    
    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 = "";
            // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
            String accessKeyId = "";
            String accessKeySecret = "";
            // 填写Bucket名称,例如examplebucket。
            String bucketName = "";
            // 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
            String objectName = "2.png";
            // 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
            // 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。
            String filePath= "C:\\Users\\93997\\Desktop\\桌面壁纸\\1.png";
    
            // 创建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();
                }
            }
        }
    }    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    image-20221110172951832

    若是你的配置没有问题,程序不会报任何代码错误!

    接下来检查一下对应阿里云的bucket文件列表是否有对应的文件:

    image-20221110173058594

    2.2、集成OSS的SDK包及封装阿里云OSS存储服务(上传、删除功能,含源码)

    配套代码:AliyunOssService-GiteeAliyunOssService-Github

    image-20220326184703797

    上传、删除方法已经封装到Utils中,controller只需要调用工具类的上传、删除即可!

    application.yml:

    # 图片文件上传
    spring:
      servlet:
        multipart:
          max-file-size: 100MB
          max-request-size: 1000MB
    
    # 阿里云OSS配置
    aliyun:
      oss:
        endpoint:   # 坐标地区示例:oss-cn-beijing.aliyuncs.com
        accessKeyId:  # 注册用户的keyID
        accessKeySecret:   # 注册用户的密钥
        bucketName:   # 桶名称 示例:pictured-st
        key:     # 存储根路径,例如:img/,以目录形式为结尾,之后图片会自动生成并添加到后缀
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    package com.changlu.config;
    
    import lombok.Data;
    import lombok.ToString;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.stereotype.Component;
    
    /**
     * @ClassName AliyunOssConfig
     * @Author ChangLu
     * @Date 3/26/2022 4:22 PM
     * @Description 阿里云OOS配置
     */
    @Component
    // 指定配置文件中自定义属性前缀
    @ConfigurationProperties(prefix = "aliyun.oss")
    @Data
    @ToString
    public class AliyunOssConfig {
    
        private String endpoint;
        private String accessKeyId;
        private String accessKeySecret;
        private String bucketName;
        private String key;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    package com.changlu.controller;
    
    import com.changlu.domain.ResponseResult;
    import com.changlu.utils.AliyunOssUtil;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.*;
    import org.springframework.web.multipart.MultipartFile;
    
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * @ClassName UploadController
     * @Author ChangLu
     * @Date 3/26/2022 5:23 PM
     * @Description Oss文件控制器
     */
    @RestController
    public class OssFileController {
    
        @Autowired
        private AliyunOssUtil aliOssUtil;
    
        /**
         * 上传图片
         * @param file
         * @return
         */
        @PostMapping("/upload")
        public ResponseResult uploadFile(@RequestParam("file")MultipartFile file){
           try {
               String visitUrl = aliOssUtil.uploadFile(file);
               Map<String,String> result = new HashMap<>(1);
               result.put("visitUrl", visitUrl);
               return new ResponseResult(200,"上传成功!", result);
           }catch (Exception e){
               e.printStackTrace();
               return new ResponseResult(500,"上传失败!");
           }
        }
    
        /**
         * 删除图片
         * @param fileName 文件名称如:b8809d28-82ec-4b06-af5f-8d3d7a16107c.jpg
         * @return
         */
        @GetMapping("/deleFile/{fileName}")
        public ResponseResult deleteFile(@PathVariable("fileName")String fileName){
            try {
                aliOssUtil.deleteFile(fileName);
                return new ResponseResult(200,"删除成功!");
            } catch (Exception e) {
                e.printStackTrace();
                return new ResponseResult(500,"删除失败!");
            }
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    import com.fasterxml.jackson.annotation.JsonInclude;
    
    /**
     * @Author changlu
     */
    @JsonInclude(JsonInclude.Include.NON_NULL)
    public class ResponseResult {
        /**
         * 状态码
         */
        private Integer code;
        /**
         * 提示信息,如果有错误时,前端可以获取该字段进行提示
         */
        private String msg;
        /**
         * 查询到的结果数据,
         */
        private T data;
    
        public ResponseResult(Integer code, String msg) {
            this.code = code;
            this.msg = msg;
        }
    
        public ResponseResult(Integer code, T data) {
            this.code = code;
            this.data = data;
        }
    
        public Integer getCode() {
            return code;
        }
    
        public void setCode(Integer code) {
            this.code = code;
        }
    
        public String getMsg() {
            return msg;
        }
    
        public void setMsg(String msg) {
            this.msg = msg;
        }
    
        public T getData() {
            return data;
        }
    
        public void setData(T data) {
            this.data = data;
        }
    
        public ResponseResult(Integer code, String msg, T data) {
            this.code = code;
            this.msg = msg;
            this.data = data;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    package com.changlu.utils;
    
    import com.aliyun.oss.OSS;
    import com.aliyun.oss.OSSClient;
    import com.aliyun.oss.OSSClientBuilder;
    import com.aliyun.oss.model.ObjectMetadata;
    import com.aliyun.oss.model.PutObjectRequest;
    import com.changlu.config.AliyunOssConfig;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    import org.springframework.web.multipart.MultipartFile;
    
    import java.io.File;
    import java.io.InputStream;
    import java.util.UUID;
    
    /**
     * @ClassName AliyunOssUtil
     * @Author ChangLu
     * @Date 3/26/2022 4:51 PM
     * @Description OSS对象存储工具类
     */
    @Component
    public class AliyunOssUtil {
    
        @Autowired
        private AliyunOssConfig aliyunOssConfig;
    
        /**
         * 创建一个OSS连接
         * @return OssClient
         */
        private OSS createOssClient(){
            String endpoint = "http://" + aliyunOssConfig.getEndpoint();
            String accessKeyId = aliyunOssConfig.getAccessKeyId();
            String accessKeySecret = aliyunOssConfig.getAccessKeySecret();
            return new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        }
    
        /**
         * 关闭连接
         * @param ossClient
         */
        private void close(OSS ossClient){
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    
        /**
         * 上传文件
         * @param file File类型
         * @return
         */
        public String uploadFile(File file){
            String key = aliyunOssConfig.getKey();
            String bucketName = aliyunOssConfig.getBucketName();
            String endpoint = aliyunOssConfig.getEndpoint();
            //1、取得保存文件路径saveFilePath:拼接目标路径 + 图片名称
            String originFileName = file.getName();
            String filePrefix = UUID.randomUUID().toString();
            String saveFileName = filePrefix + originFileName.substring(file.getName().indexOf("."));
            String saveFilePath = key + saveFileName;
            OSS ossClient = null;
            try {
                ossClient = createOssClient();
                //2、上传文件
                //第一个参数为:桶的名称;第二个参数为路径+上你的文件名,如test/1.png,若是test/test2/1.png,也会给我们自动创建目录
                //第三个参数为:文件对象
                ossClient.putObject(new PutObjectRequest(bucketName,saveFilePath , file));
            }catch (Exception e){
                e.printStackTrace();
                return null;
            }finally {
                this.close(ossClient);
            }
            //3、拼接获取公共访问地址
            String publicVisitPath = "http://" + bucketName + '.' +  endpoint + "/" + saveFilePath;
            return publicVisitPath;
        }
    
        /**
         * 上传文件
         * @param file MultipartFile类型
         * @return
         */
        public String uploadFile(MultipartFile file)throws Exception{
            String key = aliyunOssConfig.getKey();
            String bucketName = aliyunOssConfig.getBucketName();
            String endpoint = aliyunOssConfig.getEndpoint();
            //1、取得保存文件路径saveFilePath:拼接目标路径 + 图片名称
            String originFileName = file.getOriginalFilename();
            String filePrefix = UUID.randomUUID().toString();
            String saveFileName = filePrefix + originFileName.substring(originFileName.indexOf("."));
            String saveFilePath = key + saveFileName;
            OSS ossClient = null;
            try {
                ossClient = createOssClient();
                //2、上传文件
                //第一个参数为:桶的名称;第二个参数为路径+上你的文件名,如test/1.png,若是test/test2/1.png,也会给我们自动创建目录
                //第三个参数为:文件对象
                /**
                 * 阿里云OSS 默认图片上传ContentType是image/jpeg
                 * 图片链接后,图片是下载链接,而并非在线浏览链接
                 * 这里在上传的时候要解决ContentType的问题,将其改为image/jpg
                 */
                InputStream is = file.getInputStream();
                ObjectMetadata meta = new ObjectMetadata();
                meta.setContentType("image/jpg");
                ossClient.putObject(new PutObjectRequest(bucketName,saveFilePath , is, meta));
            }catch (Exception e){
                throw new RuntimeException(e);
            }finally {
                this.close(ossClient);
            }
            //3、拼接获取公共访问地址
            String publicVisitPath = "http://" + bucketName + '.' +  endpoint + "/" + saveFilePath;
            return publicVisitPath;
        }
    
    
        /**
         * 删除文件
         * @param fileName 待删除的文件名
         * @return
         */
        public void deleteFile(String fileName)throws Exception{
            String key = aliyunOssConfig.getKey();
            String bucketName = aliyunOssConfig.getBucketName();
            //1、拼接待删除路径
            String deleteFilePath = key + fileName;
            OSS ossClient = null;
            try {
                ossClient = createOssClient();
                //2、删除文件
                ossClient.deleteObject(bucketName, deleteFilePath);
            }catch (Exception e){
                throw new RuntimeException(e);
            }finally {
                this.close(ossClient);
            }
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144

    2.3、集成SpringCloud-Alibaba-OSS

    环境依赖配置

    image-20221110184737143

    pom.xml:三个版本依次为springboot2.1.8springcloud Greenwich.SR3SpringCloud Alibaba2.1.0.RELEASE

    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>2.1.8.RELEASEversion>
        <relativePath/> 
    parent>
    
    <properties>
        <java.version>1.8java.version>
        <spring-cloud.version>Greenwich.SR3spring-cloud.version>
    properties>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
    
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
        dependency>
    
        <dependency>
            <groupId>com.alibaba.cloudgroupId>
            <artifactId>spring-cloud-starter-alicloud-ossartifactId>
        dependency>
    dependencies>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
            plugin>
        plugins>
    build>
    
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-dependenciesartifactId>
                <version>${spring-cloud.version}version>
                <type>pomtype>
                <scope>importscope>
            dependency>
            <dependency>
                <groupId>com.alibaba.cloudgroupId>
                <artifactId>spring-cloud-alibaba-dependenciesartifactId>
                <version>2.1.0.RELEASEversion>
                <type>pomtype>
                <scope>importscope>
            dependency>
        dependencies>
    dependencyManagement>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    2.3.1、实现普通上传

    配套代码:springcloud-alibaba-oss-Giteespringcloud-alibaba-oss-Github

    server:
      port: 8888
    spring:
      cloud:
        alicloud:
          access-key: 
          secret-key: 
          oss:
            endpoint: 
            # 这是自定义的,需要自己来去读取
            bucketname: 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    image-20221110185700097

    接着对应demo写在了test的示例中:下面黄色框的就是我们需要自己额外编写的,其他的上传操作和之前的普通上传基本一致

    image-20221110185758897

    package com.changlu;
    
    import com.aliyun.oss.ClientException;
    import com.aliyun.oss.OSS;
    import com.aliyun.oss.OSSException;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.InputStream;
    
    /**
     * @Description:
     * @Author: changlu
     * @Date: 5:44 PM
     */
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class SpringCloudOSSApplicationTest {
    
        @Autowired
        private OSS ossClient;
    
        @Value("${spring.cloud.alicloud.oss.bucketname}")
        private String bucketName;
    
        //普通上传文件服务
        @Test
        public void test() {
            // 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
            String objectName = "4.png";
            // 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
            // 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。
            String filePath= "C:\\Users\\93997\\Desktop\\桌面壁纸\\1.png";
            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());
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } finally {
                if (ossClient != null) {
                    ossClient.shutdown();
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65

    运行一下,若是没有任何报错信息的话,那么此时说就说上传成功:

    image-20221110185915659

    image-20221110185928409


    2.3.2、获取服务端签名(web端来实现上传功能)

    后端代码

    配套代码:springcloud-alibaba-oss-Giteespringcloud-alibaba-oss-Github

    文档地址:最佳实践-web端上传数据至OSS-服务器端直传并设置上传回调

    image-20221111104552335

    pom.xml

    
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0modelVersion>
        <parent>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-parentartifactId>
            <version>2.1.8.RELEASEversion>
            <relativePath/> 
        parent>
        <groupId>com.changlugroupId>
        <artifactId>springcloud-alibaba-ossartifactId>
        <version>0.0.1-SNAPSHOTversion>
        <name>springcloud-alibaba-ossname>
        <description>Demo project for Spring Bootdescription>
        <properties>
            <java.version>1.8java.version>
            <spring-cloud.version>Greenwich.SR3spring-cloud.version>
        properties>
        <dependencies>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-webartifactId>
            dependency>
    
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-testartifactId>
                <scope>testscope>
            dependency>
    
            <dependency>
                <groupId>com.alibaba.cloudgroupId>
                <artifactId>spring-cloud-starter-alicloud-ossartifactId>
            dependency>
        dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.bootgroupId>
                    <artifactId>spring-boot-maven-pluginartifactId>
                plugin>
            plugins>
        build>
    
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloudgroupId>
                    <artifactId>spring-cloud-dependenciesartifactId>
                    <version>${spring-cloud.version}version>
                    <type>pomtype>
                    <scope>importscope>
                dependency>
                <dependency>
                    <groupId>com.alibaba.cloudgroupId>
                    <artifactId>spring-cloud-alibaba-dependenciesartifactId>
                    <version>2.1.0.RELEASEversion>
                    <type>pomtype>
                    <scope>importscope>
                dependency>
            dependencies>
        dependencyManagement>
    
    project>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66

    application.yml

    server:
      port: 8888
    spring:
      cloud:
        alicloud:
          access-key: 
          secret-key: 
          oss:
            endpoint: 
            # 这是自定义的,需要自己来去读取
            bucketname: 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    R.java:统一封装响应类

    package com.changlu.utils;
    
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * 返回数据
     * 
     * @author chenshun
     * @email sunlightcs@gmail.com
     * @date 2016年10月27日 下午9:59:27
     */
    public class R extends HashMap<String, Object> {
    	private static final long serialVersionUID = 1L;
    	
    	public R() {
    		put("code", 0);
    		put("msg", "success");
    	}
    	
    	public static R error() {
    		return error(500, "未知异常,请联系管理员");
    	}
    	
    	public static R error(String msg) {
    		return error(500, msg);
    	}
    	
    	public static R error(int code, String msg) {
    		R r = new R();
    		r.put("code", code);
    		r.put("msg", msg);
    		return r;
    	}
    
    	public static R ok(String msg) {
    		R r = new R();
    		r.put("msg", msg);
    		return r;
    	}
    	
    	public static R ok(Map<String, Object> map) {
    		R r = new R();
    		r.putAll(map);
    		return r;
    	}
    	
    	public static R ok() {
    		return new R();
    	}
    
    	public R put(String key, Object value) {
    		super.put(key, value);
    		return this;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    OssController.java:提供获取签名服务

    package com.changlu.controller;
    
    import com.aliyun.oss.OSS;
    import com.aliyun.oss.common.utils.BinaryUtil;
    import com.aliyun.oss.model.MatchMode;
    import com.aliyun.oss.model.PolicyConditions;
    import com.changlu.utils.R;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    /**
     * @Description:
     * @Author: changlu
     * @Date: 7:03 PM
     */
    @RestController
    public class OssController {
    
        @Autowired
        private OSS ossClient;
    
        @Value("${spring.cloud.alicloud.oss.bucketname}")
        private String bucketName;
    
        @Value("${spring.cloud.alicloud.access-key}")
        private String accessId;
    
        @Value("${spring.cloud.alicloud.oss.endpoint}")
        private String endpoint;
    
        @RequestMapping("/oss/policy")
        public R policy() {
            // 填写Host地址,格式为https://bucketname.endpoint。
            String host = "https://" + bucketName + "." + endpoint;
            String dirName = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
            // 设置上传到OSS文件的前缀,可置空此项。置空后,文件将上传至Bucket的根目录下。
            String dir = dirName + "/";
    
            Map<String, String> respMap = null;
            try {
                long expireTime = 30;
                long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
                Date expiration = new Date(expireEndTime);
                PolicyConditions policyConds = new PolicyConditions();
                policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
                policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);
                //生成签名
                String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
                byte[] binaryData = postPolicy.getBytes("utf-8");
                String encodedPolicy = BinaryUtil.toBase64String(binaryData);
                String postSignature = ossClient.calculatePostSignature(postPolicy);
    
                respMap = new LinkedHashMap<String, String>();
                respMap.put("accessid", accessId);
                respMap.put("policy", encodedPolicy);
                respMap.put("signature", postSignature);
                respMap.put("dir", dir);
                respMap.put("host", host);
                respMap.put("expire", String.valueOf(expireEndTime / 1000));
            } catch (Exception e) {
                // Assert.fail(e.getMessage());
                System.out.println(e.getMessage());
            }
            return R.ok().put("data", respMap);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74

    测试下:成功获取

    image-20221111105629219

    image-20221111105037230

    前端代码

    这里组件源代码可以直接可以查看谷粒商城博客笔记:谷粒商城-基础篇(详细流程梳理+代码)

    image-20221111105424010

    这里面包含了组件源代码以及实际引入项目并使用的前端案例。

    注意点

    1、每次使用完OSSClient后要进行关闭,ossClient.shutdown()。

    OSSClient不关闭,导致大量FullGC

    2、可不可以设置OSSClient为单例?

    • new OSSClient只是初始化一堆对象,并未建立长连接,如果你endpoint和权限是固定的,定义成static变量都行,只有在有实际操作时,才会httpClient.execute(),我每次都new这个客户端,是因为包装sdk给业务用时,CredentialsProvider这个是动态的
    • 建议在方法中创建OSSClient 而不是使用@Bean注入,不然容易出现Connection pool shut down。

    参考资料

    [1] 一小时学会使用springboot操作阿里云OSS实现文件上传,下载,删除(附源码)

    [2] SpringBoot整合阿里云OSS

  • 相关阅读:
    【Realtek sdk-3.4.14b】RTL8197FH-VG和RTL8812F自适应认证失败问题分析及修改
    发光太阳聚光器的蒙特卡洛光线追踪研究(Matlab代码实现)
    六级(2021/6-1) Text2
    0730~Mysql优化
    2022.07 排列组合
    [PAT练级笔记] Basic Level 1018 锤子剪刀布
    Flutter iOS上架指南
    C#WPF用户控件及自定义控件实例
    【踩坑】工作中真实踩坑,一个or让sql变慢7倍
    Shiro入门(五)Shiro自定义Realm和加密算法
  • 原文地址:https://blog.csdn.net/cl939974883/article/details/127802770