阿里云存储——服务签名直传

摘要:

服务签名直传就是后端服务签名后前端直传,Web前端直接将文件上传到OSS服务器,只是在上传文件之前请求后端获取OSS配置签名信息,Web前端拿到后和文件一起上传至OSS服务器,这样一来,文件不用传至后端上传,而是直接通过前端上传,二是OSS配置参数从后端获取,避免了在前端配置而导致暴露的风险

阿里云对象存储开通教程:

https://blog.csdn.net/u014494148/article/details/108858360

一:步骤

  1. 前端JS请求后端拿到OSS签名信息
  2. 前端带着签名信息和文件一起上传OSS服务器
  3. 前端上传成功返回地址传至后端
  4. 后端拿到提交的数据和文件地址保存到数据库

二:引入阿里云存储依赖

<!--阿里云Oss云存储依赖-->
<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>3.15.0</version>
</dependency>

三:yml配置签名信息

file:
    alicloud:
        bucket-name: itsource-test #上传空间bucket
        access-key: LTAI5tMgcQ6iE3JfA9gs7UV1 #你的key
        secret-key: mSR0rLYBl71MXO6ST8YUzHTH0XIMgV #你的秘钥
        endpoint: oss-cn-chengdu.aliyuncs.com  #上传端点
        dir: "director" # 自定义用户上传文件时的文件路径前缀

 四:将yml配置信息读取为常量

package cn.itsource.constants;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Data
@Component
@ConfigurationProperties(prefix = "file.alicloud")
public class AlicloudOSSProperties {

    private String bucketName;
    private String accessKey;
    private String secretKey;
    private String endpoint;
    private String dir;
}

五:OSS文件上传接口

package cn.itsource.web.controller;

import cn.itsource.constants.AlicloudOSSProperties;
import cn.itsource.result.JsonResult;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;

@RestController
public class AlicloudOSSController {

    @Autowired
    private AlicloudOSSProperties properties;


    @GetMapping("/oss/sign")
    public JsonResult ossSign(){
        // host的格式为 bucketname.endpoint
        String host = "https://" + properties.getBucketName() + "." + properties.getEndpoint();
        // 用户上传文件时文件路径前缀
        String dir = properties.getDir();
        // 创建OSSClient实例。
        OSS ossClient = null;
        try {
            //策略过期时间
            long expireTime = 100;
            long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
            Date expiration = new Date(expireEndTime);

            // PostObject请求最大可支持的文件大小为5 GB,即CONTENT_LENGTH_RANGE为5*1024*1024*1024。
            PolicyConditions policyConds = new PolicyConditions();
            policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
            policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);

            // 创建OSSClient实例。
            ossClient = new OSSClientBuilder()
                .build(properties.getEndpoint(), properties.getAccessKey(), properties.getSecretKey());

            String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
            byte[] binaryData = postPolicy.getBytes("utf-8");
            String encodedPolicy = BinaryUtil.toBase64String(binaryData);
            //签名
            String postSignature = ossClient.calculatePostSignature(postPolicy);

            //返回签名及OSS相关参数
            Map<String, String> respMap = new LinkedHashMap<String, String>();
            respMap.put("accessid", properties.getAccessKey());
            respMap.put("policy", encodedPolicy);
            respMap.put("signature", postSignature);
            respMap.put("dir", dir);
            respMap.put("host", host);
            respMap.put("expire", String.valueOf(expireEndTime / 1000));

            return JsonResult.success(respMap);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(e.getMessage());
        } finally {
            if(ossClient != null){
                ossClient.shutdown();
            }
        }
        return null;
    }
}

六:前端element-ui上传组件

<el-upload
         class="upload-demo"
         action="http://你的bucket.oss-cn-chengdu.aliyuncs.com"
         :data="uploadData"
         :before-upload="beforeUpload"
         :on-success="handleSuccess"
         :file-list="fileList"
         list-type="picture">
    <el-button size="small" type="primary">点击上传</el-button>
    <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
</el-upload>

七:前端vue方法

export default {
    data() {
        return {
            uploadData: {  //提交到OSS的参数
                policy: '',
                signature: '',
                key: '',
                ossaccessKeyId: '',
                dir: '',
                host: ''
            }
        };
    },
    methods: {
        getUUID() {
            var s = [];
            var hexDigits = "0123456789abcdef";
            for (var i = 0; i < 36; i++) {
                s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
            }
            s[14] = "4"; // bits 12-15 of the time_hi_and_version field to 0010
            s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
            s[8] = s[13] = s[18] = s[23] = "-";
            var uuid = s.join("");
            return uuid;
        },
        async beforeUpload(){
            await this.$http.get("/file/oss/sign").then(response=>{
                //设置相关的参数
                var resultObj = response.data.resultObj;
                this.uploadData.policy = resultObj.policy;
                this.uploadData.signature = resultObj.signature;
                this.uploadData.ossaccessKeyId = resultObj.accessid;
                //上传的文件名,使用UUID处理一下
                this.uploadData.key = resultObj.dir + '/'+this.getUUID()+'_${filename}';
                this.uploadData.dir = resultObj.dir;
                this.uploadData.host = resultObj.host;
            });
        },
        handleSuccess(res, file) {
            //上传的完整的文件地址
            var urlPath = this.uploadData.host + '/' + this.uploadData.key.replace("${filename}",file.name) ;
            this.addForm.pic = urlPath;
            this.$message({message: '上传成功,图片地址:'+this.employee.logo, type: 'success' });
        },
        handleRemove(file, fileList) {

        },
        handlePreview(file) {

        }
    }

 

posted @ 2022-09-06 14:59  yyybl  阅读(201)  评论(0)    收藏  举报