流程介绍
本示例中,Web端向服务端请求签名,然后直接上传,不会对服务端产生压力,而且安全可靠。但本示例中的服务端无法实时了解用户上传了多少文件,上传了什么文件。如果想实时了解用户上传了什么文件,可以采用服务端签名直传并设置上传回调。
落地实现
添加依赖
<!--OSS SDK-->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.10.2</version>
</dependency>
步骤一、后端签名加密
@RestController
public class OSSController {
@CrossOrigin //解决跨域
@RequestMapping("/oss/policy")
public Map<String,String> policy(@RequestParam("fileName") String fileName){
String accessId = ""; // 请填写您的AccessKeyId。
String accessKey = ""; // 请填写您的AccessKeySecret。
String endpoint = "oss-cn-beijing.aliyuncs.com"; // 请填写您的 endpoint。
String bucket = ""; // 请填写您的 bucketname 。
String host = "https://" + bucket + "." + endpoint; // host的格式为 bucketname.endpoint
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
String date = simpleDateFormat.format(new Date());
String dir = "tuling-test/"+date+"/"; // 用户上传文件时指定的前缀。
//文件名生成
fileName = UUID.randomUUID().toString() + fileName.substring(fileName.lastIndexOf("."));
String key = dir + fileName;
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessId, accessKey);
try {
long expireTime = 30;
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);
String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
byte[] binaryData = postPolicy.getBytes("utf-8");
String encodedPolicy = BinaryUtil.toBase64String(binaryData);
String postSignature = ossClient.calculatePostSignature(postPolicy);
Map<String, String> respMap = new LinkedHashMap<String, String>();
respMap.put("accessid", accessId);//您的AccessKeyId。
respMap.put("policy", encodedPolicy);//Policy规定了请求表单域的合法性。
respMap.put("signature", postSignature);//根据AccessKey Secret和Policy计算的签名信息,OSS验证该签名信息从而验证该Post请求的合法性。
respMap.put("dir", dir); //前缀
respMap.put("host", host); // "https://" + bucketname + '.' + endpoint; (前端请求oss服务路径)
respMap.put("key", key); //dir + fileName (上传Object的名称。)
respMap.put("expire", String.valueOf(expireEndTime / 1000));
// respMap.put("expire", formatISO8601Date(expiration));
return respMap;
} catch (Exception e) {
// Assert.fail(e.getMessage());
System.out.println(e.getMessage());
} finally {
ossClient.shutdown();
}
return null;
}
}
步骤二、配置客户端
<template>
<div id="upload">
<el-upload
class="upload-demo"
:action="objectData.host"
:before-upload="getPolicy"
:data="objectData"
:on-preview="handlePreview"
:on-remove="handleRemove"
: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>
</div>
</template>
<script>
import {request} from '../network/request'
import axios from "axios";
export default {
name: "upfile",
data() {
return {
fileList: [{name: 'food.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}, {name: 'food2.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}],
objectData: {
OSSAccessKeyId: "",
policy: "",
Signature: "",
key: "",
host: '',
dir: ''
}
};
},
created() {
},
methods: {
handleRemove(file, fileList) {
console.log(file, fileList);
},
handlePreview(file) {
console.log(file);
},
getPolicy(file){
console.log(file)
const _this = this;
return new Promise(((resolve, reject) => {
request({
url: 'oss/policy',
params: {
fileName: file.name
}
})
.then(res=>{
_this.objectData.OSSAccessKeyId = res.data.accessid; // Bucket拥有者的AccessKey ID。
_this.objectData.policy = res.data.policy; //Policy规定了请求表单域的合法性。
_this.objectData.Signature = res.data.signature;//根据AccessKey Secret和Policy计算的签名信息,OSS验证该签名信息从而验证该Post请求的合法性。
_this.objectData.dir = res.data.dir;//前缀
_this.objectData.host = res.data.host;// "https://" + bucketname + '.' + endpoint; (前端请求oss服务路径)
//_this.objectData.key = res.data.dir + "${filename}";
_this.objectData.key = res.data.key;//dir + fileName (上传Object的名称。)
_this.fileList.push({name: res.data.key,url: res.data.host+"/"+res.data.key})
resolve(true);
})
.catch(err=>{
console.log(err);
reject(false);
})
}))
}
}
}
</script>
<style scoped>
#upload{
width: 400px;
}
</style>
步骤三、修改CORS
客户端进行表单直传到OSS时,会从浏览器向OSS发送带有Origin的请求消息。OSS对带有Origin头的请求消息会进行跨域规则(CORS)的验证。因此需要为Bucket设置跨域规则以支持Post方法。
- 登录OSS管理控制台。
- 单击Bucket列表,之后单击目标Bucket名称。
- 单击权限管理 > 跨域设置,在跨域设置区域单击设置。
- 单击创建规则,配置如下图所示。