阿里oss 客户端上传学习

参考大佬的 demo

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
spring:
  resources:
    static-locations: classpath:templates/

# OSS相关配置信息
aliyun:
  oss:
    endpoint: mtest-oss.oss-cn-beijing.aliyuncs.com # oss对外服务的访问域名
    accessKeyId:  # 访问身份验证中用到用户标识
    accessKeySecret:  # 用户用于加密签名字符串和oss用来验证签名字符串的密钥
    bucketName: mtest-oss # oss的存储空间
    policy:
      expire: 30 # 签名有效期(S)
    maxSize: 10 # 上传文件大小(M)
    callback: http://30og365639.wicp.vip/aliyun/oss/callback # 文件上传成功后的回调地址
    dir:
      prefix: oss/images/ # 上传文件夹路径前缀 `

image-20211120153421911

自己写的客户端上传代码【用于使用参考】

 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
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
  </head>
  <body>
    <form method="POST" enctype="multipart/form-data">
      上传文件:
      <input
        multiple
        id="file"
        type="file"
        name="file"
        placeholder="上传文件"
      />
      <button id="upload" type="button">上传</button>
    </form>
    <script>
      $("#upload").click(() => {
        getPolicyAndUpload();
        //upload();
      });
    </script>
    <script>
      function getPolicyAndUpload() {
        let file = document.getElementById("file").files[0];
        $.ajax({
          url: "/free/policy",
          type: "get",
          processData: false,
          contentType: false,
        }).success((res) => {
          console.log(res);
            //这个是 上传的 token对象
          let uploadTokenObject = res.resultContent;
          upload(file,uploadTokenObject)
          // let uploadId = res.data.uploadId;
          // console.log('uploadId',uploadId);
          // //
          // upload(uploadId)
        });
      }
    </script>

    <script>
      //设置每个切片大小 , 2M
      let bytesPerPiece = 1024 * 1024 * 2;

      //上传文件函数
      function upload(file, ossToken) {
        const filename = file.name;
        let formData = new FormData();
        //注意formData里append添加的键的大小写
        console.log(ossToken);
        formData.append("key", ossToken.dir + filename); //存储在oss的文件路径
        formData.append("OSSAccessKeyId", ossToken.accessid); //accessKeyId
        formData.append("policy", ossToken.policy); //policy
        formData.append("Signature", ossToken.signature); //签名
        formData.append("callback", ossToken.callback); //回调
        formData.append("success_action_status", 200); //成功后返回的操作码
        //如果是base64文件,那么直接把base64字符串转成blob对象进行上传就可以了
        formData.append("file", file);

        // axios.post(ossToken.host,formData,{
        //     'Content-Type':'multipart/form-data'
        // }).then(res=>{
        //     console.log(res)
        //     this.srcList.push(res.data.resultContent.filename);
        // })
        $.ajax({
          url: `${ossToken.host}`,
          type: "post",
          data:formData,
          contentType:'multipart/form-data',
          processData: false,
          contentType: false,
        }).success((res)=> {
          console.log(res);

        }).error((res) => {
          console.log(res)
        })
      }
    </script>
  </body>
</html>

后端代码

 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
package io.github.lyr2000.dissertation.controller.openapi;

// import io.github.lyr2000.dissertation.components.OssAuthcUtil;
import io.github.lyr2000.dissertation.pojo.dto.ResultBean;
import io.github.lyr2000.dissertation.service.FileService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

/**
 * @author lyr
 * @description oss鉴权
 * @create 2021-11-20 14:42
 */
@Slf4j
@RestController
@RequestMapping("/free/")
public class OssController {
    @Resource
    private FileService ossService;



    @GetMapping("/policy")
    public ResultBean policy() {
        ResultBean result = ossService.getPolicy();
        log.info("服务端生成签名:{}",result);
        return result;
    }


    @PostMapping("/callback")
    public ResultBean callback(HttpServletRequest request) {
        ResultBean ossCallbackResult = ossService.callback(request);
        log.info("oss成功的回调:{}",ossCallbackResult);
        return ossCallbackResult;
    }
}
  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
package io.github.lyr2000.dissertation.service.impl;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import io.github.lyr2000.common.dto.Result;
import io.github.lyr2000.dissertation.components.AliYunOssPropertis;
import io.github.lyr2000.dissertation.pojo.dto.OssCallbackParam;
import io.github.lyr2000.dissertation.pojo.dto.ResultBean;
import io.github.lyr2000.dissertation.service.FileService;
import lombok.Data;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author lyr
 * @description 阿里OSS 文件
 * @create 2021-11-19 15:39
 */
@Slf4j
@Service
@ToString
@Data
public class AliyunOssFileServiceImpl implements FileService {

    // @Value("${aliyun.oss.accessKey}")
    // private String accessKey;
    //
    // @Value("${aliyun.oss.accessKeySecret}")
    // private String accessKeySecret;
    @Resource
    private AliYunOssPropertis propertis;

    @Override
    public Result<?> uploadFile(MultipartFile file, String originLocalFileName, String uploadUID,
                                int partCnt, int totalCnt) {
        return null;
    }

    @Override
    public Result<?> uploadVideo(MultipartFile file) {
        return null;
    }


    @Value("${aliyun.oss.policy.expire}")
    private int ALIYUN_OSS_EXPIRE;
    @Value("${aliyun.oss.maxSize}")
    private int ALIYUN_OSS_MAX_SIZE;
    @Value("${aliyun.oss.callback}")
    private String ALIYUN_OSS_CALLBACK;
    @Value("${aliyun.oss.bucketName}")
    private String ALIYUN_OSS_BUCKET_NAME;
    @Value("${aliyun.oss.endpoint}")
    private String ALIYUN_OSS_ENDPOINT;
    @Value("${aliyun.oss.dir.prefix}")
    private String ALIYUN_OSS_DIR_PREFIX;

    @PostConstruct
    @Profile({"test","tests"})
    void printProfiles() {
        log.info("aliyun profiles = {}",this.toString());
    }

    /**
     * //  * 生成前端直传 token
     * //  * @return
     * //
     */
    // @Override
    // public String generateUploadToken() {
    //     return null;
    // }
    @Resource
    private OSSClient ossClient;

    @Override
    public ResultBean getPolicy() {
        JSONObject resultBean = new JSONObject();
        // 存储目录
        String dir = ALIYUN_OSS_DIR_PREFIX  + "/";
        // 签名有效期
        long expireEndTime = System.currentTimeMillis() + ALIYUN_OSS_EXPIRE * 1000;
        Date expiration = new Date(expireEndTime);
        // 文件大小
        long maxSize = ALIYUN_OSS_MAX_SIZE * 1024 * 1024;
        // 回调
        OssCallbackParam callback = new OssCallbackParam();
        callback.setCallbackUrl(ALIYUN_OSS_CALLBACK);
        callback.setCallbackBody("filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}");
        callback.setCallbackBodyType("application/x-www-form-urlencoded");
        // 提交节点
        String action = "https://"+propertis.getEndpoint();
        /*"https://" + ALIYUN_OSS_ENDPOINT;*/
        try {
            PolicyConditions policyConds = new PolicyConditions();
            policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, maxSize);
            policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);
            String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
            byte[] binaryData = postPolicy.getBytes("utf-8");
            String policy = BinaryUtil.toBase64String(binaryData);
            String signature = ossClient.calculatePostSignature(postPolicy);
            String callbackData = BinaryUtil.toBase64String(JSONUtil.parse(callback).toString().getBytes("utf-8"));
            resultBean.put("accessid", ossClient.getCredentialsProvider().getCredentials().getAccessKeyId());
            resultBean.put("policy", policy);
            resultBean.put("signature", signature);
            resultBean.put("dir", dir);
            resultBean.put("expire", String.valueOf(expireEndTime / 1000));
            resultBean.put("callback", callbackData);
            resultBean.put("host", action);
            // 返回结果
        } catch (Exception e) {
            log.error("签名生成失败", e);
            return new ResultBean(ResultBean.RESCODE_SIGNATION_FAILED, ResultBean.RESMSG_SIGNATION_FAILED);
        }
        return new ResultBean(ResultBean.RESCODE_SUCCESS, ResultBean.RESMSG_SUCCESS, resultBean);
    }

    @Override
    public ResultBean callback(HttpServletRequest request) {
        JSONObject resultBean = new JSONObject();
        String filename = request.getParameter("filename");
        filename = "https://".concat(ALIYUN_OSS_ENDPOINT).concat("/").concat(filename);
        resultBean.put("filename", filename);
        resultBean.put("size", request.getParameter("size"));
        resultBean.put("mimeType", request.getParameter("mimeType"));
        resultBean.put("width", request.getParameter("width"));
        resultBean.put("height", request.getParameter("height"));

        return new ResultBean(ResultBean.RESCODE_SUCCESS, ResultBean.RESMSG_SUCCESS, resultBean);
    }
    // @Override
    // public Result<?> uploadFile(MultipartFile file, int sliceIndex, int totalCnt, String originName) {
    //      return null;
    // }
}

配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13

aliyun:
  oss:
    endpoint: "ltest.oss-cn-guangzhou.aliyuncs.com"
    accessKey: "yourKEY"
    accessKeySecret: "your  secret"
    bucketName: "ltest"
    callback: "http://lyr-2000.natapp1.cc/free/callback"
    maxSize: 1000 # 上传文件最大限制在10M
    policy:
      expire: 80 #签名有效期(S)
    dir:
      prefix: "file"

其他方式

生成 sts令牌的方式

https://www.icode9.com/content-4-780260.html

https://blog.csdn.net/weixin_39852181/article/details/106740139

https://blog.csdn.net/qq_39521532/article/details/113748064?spm=1001.2101.3001.6650.6&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-6.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-6.no_search_link

php版本