后端环境:java8、spring boot、jdk1.8.191
前端环境:vue3.2、vite4.3、axios1.3 (Geeker Admin初始化框架)
项目思路:前端上传文件使用el-upload的http-request事件覆盖默认xhr行为,手动请求后端签名接口获取签名,通过axios直接将文件上传到阿里云。
一、阿里云配置
- 使用RAM访问控制,创建子用户后保存AccessKey、AccessKey ID
- Bucket数据安全设置跨域来源为服务器前端地址,例:http://127.0.0.1:8080
二、后端签名
- 创建AliyunConfig类保存阿里云配置参数
public class AliyunConfig {
// RAM用户AccessKey ID
public static final String accessId = "*****";
// RAM用户AccessKey
public static final String accessKey = "*****";
// bucket地域地址
public static final String endpoint = "oss-cn-guangzhou.aliyuncs.com";
// bucke名称
public static final String bucket = "bucket_name";
// 使用bucke名称 + bucket地域地址组合成前端上传地址
public static final String host = "https://bucket_name.oss-cn-guangzhou.aliyuncs.com";
// 文件存放目录
public static final String dir = "";
}
- 签名接口
@RestController
@RequestMapping("/upload")
public class OSSController {
@GetMapping(value = "/get/signature")
// 创建OSS客户端,使用AliyunConfig中指定的endpoint、accessId和accessKey
OSS ossClient = new OSSClientBuilder().build(AliyunConfig.endpoint, AliyunConfig.accessId, AliyunConfig.accessKey);
long expireTime = 30L;
long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
Date expiration = new Date(expireEndTime);
// 设置PostObject请求的条件,其中COND_CONTENT_LENGTH_RANGE表示文件大小范围,此处设置为0到1048576000字节(即1GB)
PolicyConditions policyConds = new PolicyConditions();
policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, AliyunConfig.dir);
String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
byte[] binaryData = new byte[0];
binaryData = postPolicy.getBytes(StandardCharsets.UTF_8);
String encodedPolicy = BinaryUtil.toBase64String(binaryData);
String postSignature = ossClient.calculatePostSignature(postPolicy);
// 构造返回的OSS签名信息对象
AliyunOssSignature res = new AliyunOssSignature(AliyunConfig.accessId, encodedPolicy, postSignature, AliyunConfig.dir, AliyunConfig.host, String.valueOf(expireEndTime / 1000),null);
ossClient.shutdown();
return ResponseResult.success(res);
}
}
三、前端上传
1、获取签名接口
export namespace Upload {
export interface ResSignature {
accessid: string;
policy: string;
signature: string;
dir: string;
host: string;
expire: string;
callback: string;
}
}
export const getUploadSignature = () => {
return http.get<Upload.ResSignature>("/upload/get/signature");
};
2、使用el-upload上传
<el-upload
:http-request="handleHttpUpload">
<!-- 其他配置项 -->
</el-upload>
const handleHttpUpload = async (options: UploadRequestOptions) => {
let formData = new FormData();
const filename = `${generateUUID()}${options.file.name}`;
formData.append("key", filename);
formData.append("file", options.file);
try {
const ossConfig = await getUploadSignature();
const { accessid, policy, signature, host } = ossConfig.data;
formData.append("OSSAccessKeyId", accessid);
formData.append("policy", policy);
formData.append("signature", signature);
await axios.post(host, formData, {
headers: {
"Content-Type": "multipart/form-data"
}
});
...
} catch (error) {
...
}
};
前端具体框架封装请查看(Geeker Admin初始化框架) UploadImg组件,只需修改handleHttpUpload方法即可