0. 准备工作
0.1 oss跨域设置
前往 bucket
中的 权限管理 -> 跨域设置
并如图进行如下设置:
0.2 创建RAM 子用户
其实不创建也可以,但是强烈建议创建一个子用户,因为主体账号含有至高权限,创建子用户可以进行更细粒度的权限管控保证账号资源安全。
创建好后保存好你的子用户 AssessKeyId
和 AssessKeySecret
以及 bucket名称
和 endpoint
(地域),后面将会用到
0.3 两种上传方式的不同点
POSTObject方式
采用表单上传,使用element
的upload组件
的话可以看到上传进度。PutObject方式
分简单上传和分片上传两种,只有分片上传才能获取到上传进度(其实就是可以知道上传了几个分片),并且分片上传可以断点续传,没有测试POSTObject方式能不能断点。- 在配置方面,POSTObject 比 PutObject要简单些。
1. PostObject 方式
1.1 后端(Java)代码如下
首先导入 Maven 依赖
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.10.2</version>
</dependency>
代码:
private static final String OSS_ENDPOINT = "oss-cn-beijing.aliyuncs.com";
private static final String ACCESS_KEY_ID = "LT***************koSL";
private static final String ACCESS_KEY_SECRET = "a0dXW*****************sSZqt";
public static JSONObject getPostPolicy() throws UnsupportedEncodingException, JSONException {
OSS ossClient=new OSSClientBuilder().build(OSS_ENDPOINT,ACCESS_KEY_ID,ACCESS_KEY_SECRET);
// host的格式为 bucketname.endpoint
String host = StringFormatter.concat("https://", BUCKET_NAME, ".", OSS_ENDPOINT).getValue();
// callbackUrl为 上传回调服务器的URL,请将下面的IP和Port配置为您自己的真实信息。
// String callbackUrl = "http://88.88.88.88:8888";
// 每一天产生一个文件夹
// 用户上传文件时指定的前缀,如果是 / 则自动检测为文件夹。
String dir = LocalDate.now().toString() + "/";
JSONObject jsonObject = new JSONObject();
//过期时间 100 秒
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);
String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
byte[] binaryData = postPolicy.getBytes(StandardCharsets.UTF_8);
String encodedPolicy = BinaryUtil.toBase64String(binaryData);
String postSignature = ossClient.calculatePostSignature(postPolicy);
jsonObject.put("OSSAccessKeyId", ACCESS_KEY_ID);
jsonObject.put("policy", encodedPolicy);
jsonObject.put("signature", postSignature);
jsonObject.put("dir", dir);
jsonObject.put("host", host);
jsonObject.put("expire", String.valueOf(expireEndTime / 1000));
return jsonObject;
}
1.2 前端
<template>
<div>
<el-upload style="width: 340px" class="upload-demo" drag
action="https://***你的bucket名称****.***你的bucket地域***.aliyuncs.com"
:file-list="files"
:auto-upload="true"
:before-upload="beforeLoad"
:on-success="onSuccess"
:data="extraData"
:before-remove="beforeRemove">
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<div class="el-upload__tip" slot="tip">不超过500kb</div>
</el-upload>
</div>
</template>
<script>
import {postPolicy} from "@/network/details/ossPolicy";
export default {
name: "upload",
data: () => ({
statusMsg: "",
//post方式的表单域信息
extraData: {},
files: []
}),
watch: {
statusMsg(val) {
console.log(val)
}
},
methods: {
// 因为向后端请求policy是异步的,我们这里同步处理就加上async
async beforeLoad(file) {
console.log("beforeLoad")
console.log(file)
//同步处理加上 await
await postPolicy().then(res => {
this.extraData = {...res.data}
// key就是上传的文件的路径,这个是postobject的必须参数
this.extraData.key = res.data.dir + file.uid + "_" + file.name
console.log(res)
console.log(this.extraData)
})
},
beforeRemove(file) {
console.log("beforeRemove")
let i = this.files.indexOf(file)
this.files.splice(i, 1)
},
onSuccess() {
console.log("onSuccess")
},
// 停止上传
stop() {
console.log("stop")
this.statusMsg = '停止上传';
if (ossClient) {
ossClient.cancel();
} else {
this.statusMsg = '停止失败';
}
}
}
}
</script>
<style scoped>
</style>
2. PutObject 方式
2.0 配置
- 此步骤请参考官方文档 STS临时访问凭证 配置好后再把相关配置填入代码中
2.1 后端(Java)代码如下
首先导入 Maven 依赖
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-sts</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.4.6</version>
</dependency>
代码
private static final String STS_ENDPOINT = "sts.***你的地域名***.aliyuncs.com";
private static final String ACCESS_KEY_ID = "LTA****************SL";
private static final String ACCESS_KEY_SECRET = "a0******************Zqt";
public static Map<String, String> getStsPolicy() {
// todo
String roleArn = "acs:ram::18*************851:role/*****";
long durationTime = 3600L;
// 填写步骤3获取的角色ARN。
// 自定义角色会话名称,用来区分不同的令牌,例如可填写为SessionTest。
String roleSessionName = "SessionTest";
String policy = "{\n" +
" \"Version\": \"1\",\n" +
" \"Statement\": [\n" +
" {\n" +
" \"Effect\": \"Allow\",\n" +
" \"Action\": \"oss:PutObject\",\n" +
" \"Resource\": [\n" +
" \"acs:oss:*:*:********/\",\n" +
" \"acs:oss:*:*:********/*\"\n" +
" ]\n" +
" }\n" +
" ]\n" +
"}";
Map<String, String> res = null;
try {
res = new HashMap<>();
// regionId表示RAM的地域ID。以华东1(杭州)地域为例,regionID填写为cn-hangzhou。也可以保留默认值,默认值为空字符串("")。
String regionId = "";
// 添加endpoint。适用于Java SDK 3.12.0及以上版本。
DefaultProfile.addEndpoint(regionId, "Sts", STS_ENDPOINT);
// 添加endpoint。适用于Java SDK 3.12.0以下版本。
// DefaultProfile.addEndpoint(endpointName, "", regionId, product: "Sts", stsEndpoint);
// 构造default profile。
IClientProfile profile = DefaultProfile.getProfile(regionId, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
// 构造client。
DefaultAcsClient client = new DefaultAcsClient(profile);
final AssumeRoleRequest request = new AssumeRoleRequest();
// 适用于Java SDK 3.12.0及以上版本。
request.setSysMethod(MethodType.POST);
// 适用于Java SDK 3.12.0以下版本。
//request.setMethod(MethodType.POST);
request.setRoleArn(roleArn);
request.setRoleSessionName(roleSessionName);
// 如果policy为空,则用户将获得该角色下所有权限。
request.setPolicy(policy);
// 设置临时访问凭证的有效时间为3600秒。
request.setDurationSeconds(durationTime);
final AssumeRoleResponse response = client.getAcsResponse(request);
AssumeRoleResponse.Credentials credentials = response.getCredentials();
System.out.println("Expiration: " + credentials.getExpiration());
System.out.println("Access Key Id: " + credentials.getAccessKeyId());
System.out.println("Access Key Secret: " + credentials.getAccessKeySecret());
System.out.println("Security Token: " + credentials.getSecurityToken());
System.out.println("RequestId: " + response.getRequestId());
res.put("accessKeyId", credentials.getAccessKeyId());
res.put("accessKeySecret", credentials.getAccessKeySecret());
res.put("securityToken", credentials.getSecurityToken());
} catch (ClientException e) {
System.out.println("Failed:");
System.out.println("Error code: " + e.getErrCode());
System.out.println("Error message: " + e.getErrMsg());
System.out.println("RequestId: " + e.getRequestId());
}
return res;
}
2.2 前端代码如下
<template>
<div>
<el-upload style="width: 340px" class="upload-demo" drag
action=""
:http-request="onUpload"
:file-list="files"
:auto-upload="true"
:before-upload="beforeLoad"
:on-success="onSuccess"
:before-remove="beforeRemove">
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<div class="el-upload__tip" slot="tip">不超过500kb</div>
</el-upload>
</div>
</template>
<script>
import {stsPolicy,postPolicy} from "@/network/details/stsPolicy";
const OSS = require('ali-oss');
let ossClient = null; // oss客户端实例
const partSize = 1024 * 1024 * 60; // 每个分片大小(byte)-我设置了60兆
const parallel = 5; // 同时上传的分片数
const checkpoints = {}; // 所有分片上传文件的检查点
export default {
name: "upload",
data: () => ({
statusMsg: "",
progressValue: 0,
showValue: 0,
extraData: {},
files: []
}),
watch: {
statusMsg(val) {
console.log(val)
}
},
created() {
// stsPolicy().then(res => {
// let {accessKeyId, accessKeySecret, securityToken} = res.data;
// this.extraData = {
// accessKeyId: accessKeyId,
// accessKeySecret: accessKeySecret,
// stsToken: securityToken,
// bucket: "clipboard-share",//todo
// secure: true,
// region: "oss-cn-beijing",//todo
// }
// })
},
methods: {
beforeLoad(file) {
console.log("beforeLoad")
console.log(file)
this.files.push(file)
},
beforeRemove(file) {
console.log("beforeRemove")
let i = this.files.indexOf(file)
this.files.splice(i, 1)
},
//清空
clearInfo() {
this.statusMsg = ""
this.$refs.bigMap4UploadFile.value = ""
this.progressValue = 0
this.showValue = 0
},
onSuccess() {
console.log("onSuccess")
},
//上传
onUpload() {
console.log("onUpload")
this.statusMsg = '上传中';
//获取临时sts凭证
stsPolicy().then(res => {
let {accessKeyId, accessKeySecret, securityToken} = res.data;
ossClient = new OSS({
accessKeyId: accessKeyId,
accessKeySecret: accessKeySecret,
stsToken: securityToken,
bucket: "***你的bucket名称***",//todo
secure: true,
region: "***你的oss地域名***",//todo
});
if (ossClient) {
this.files.forEach(file => {
console.log(file)
// 如果文件大学小于分片大小,使用普通上传,否则使用分片上传
if (file.size < partSize) {
this.showValue = 0
this.commonUpload(file);
} else {
this.showValue = 1
this.multipartUpload(file);
}
});
} else {
console.log("ossClient null")
this.statusMsg = 'initOSSClient异常空,请刷新重试或联系管理员'
}
}).catch(err => {
console.log(err)
this.statusMsg = 'initOSSClient异常,请刷新重试或联系管理员'
})
},
//添加文件夹名字
getDateFolder() {
console.log("getDateFolder")
let t = new Date();
let timeStr = "";
timeStr = timeStr + t.getFullYear();//年
timeStr = timeStr + (t.getMonth() + 1);//月,因为从0开始,所以需要加1
timeStr = timeStr + t.getDate();//日
return timeStr
},
// 普通上传
commonUpload(file) {
console.log("commonUpload")
console.log(file[0])
let fileName = file.name;
let dateFolder = this.getDateFolder();
return ossClient.put(dateFolder + "/" + new Date().getTime() + "_" + fileName, file).then(result => {
console.log(`Common upload ${file.name} succeeded, result === `, result)
this.statusMsg = '上传成功';
// this.files.push(file)
this.$emit('change', result.url)
}).catch(err => {
this.statusMsg = '上传失败';
this.$emit('change', "")
console.log(`Common upload ${file.name} failed === `, err);
});
},
// 分片上传
multipartUpload(file) {
console.log("multipartUpload")
let fileName = file.name;
let dateFolder = this.getDateFolder();
let dateStr = new Date().getTime();
return ossClient.multipartUpload(dateFolder + "/" + dateStr + "_" + fileName, file, {
parallel,
partSize,
progress: this.onMultipartUploadProgress
}).then(result => {
this.statusMsg = '上传成功';
// this.files.push(file)
console.log(result)
let url = `http://aaa.bbb.aliyuncs.com/${dateFolder}/${dateStr}_${fileName}`;//a是bucket,b是region。//todo
this.$emit('change', url)
}).catch(err => {
this.statusMsg = '上传失败';
this.$emit('change', "")
console.log(`Multipart upload ${file.name} failed === `, err);
this.progressValue = 0
this.showValue = 0
});
},
// 分片上传进度改变回调
onMultipartUploadProgress(progress, checkpoint) {
console.log(`${checkpoint.file.name} 上传进度 ${progress}`);
checkpoints[checkpoint.uploadId] = checkpoint;
this.progressValue = Math.round(progress * 100)
},
// 停止上传
stop() {
console.log("stop")
this.statusMsg = '停止上传';
if (ossClient) {
ossClient.cancel();
} else {
this.statusMsg = '停止失败';
}
}
}
}
</script>
<style scoped>
</style>
3 预览图
其实也没啥预览的