前言
阿里云oss上传文件包含有好多SDK,一般像客户端的百度云盘这样的C端会使用如java相关的SDK,而浏览器端,也就是web端最好使用browser.js相关的SDK,下面就来讲解下如何使用,希望能够帮助到大家。
配置ram权限获取sts token和跨域支持
在使用阿里云OSS上传文件之前,要提前配置好ram相关权限,官方文档有说明,详细请看使用STS临时访问凭证访问OSS,配置时,要注意两点:
1、因为会使用上传和下载两种权限,所以应该使用下面权限策略(xxx为你的路径):
{
"Version": "1",
"Statement": [
{
"Effect": "Allow",
"Action": [
"oss:PutObject",
"oss:GetObject"
],
"Resource": [
"acs:oss:*:*:xxx",
"acs:oss:*:*:xxx/*"
]
}
]
}
配置好之后,我们再来配置后台,返回sts token
给前端
@Override
public AssumeRoleResponse getAcsForUploadFile(String userName) {
// STS接入地址,例如sts.cn-hangzhou.aliyuncs.com。
String endpoint = aliyunOssConfig.getRamStsEndpoint();
// 填写步骤1生成的访问密钥AccessKey ID和AccessKey Secret。
String AccessKeyId = aliyunOssConfig.getRamAccessKeyId();
String accessKeySecret = aliyunOssConfig.getRamAccessKeySecret();
// 填写步骤3获取的角色ARN。
String roleArn = aliyunOssConfig.getRamRoleArn();
// 自定义角色会话名称,用来区分不同的令牌,例如可填写为SessionTest。
String roleSessionName = userName;
// 以下Policy用于限制仅允许使用临时访问凭证向目标存储空间examplebucket上传文件。
// 临时访问凭证最后获得的权限是步骤4设置的角色权限和该Policy设置权限的交集,即仅允许将文件上传至目标存储空间examplebucket下的exampledir目录。
// String policy = "{" +
// " \"Version\": \"1\", " +
// " \"Statement\": [" +
// " {\n" +
// " \"Action\": [" +
// " \"oss:PutObject\"" +
// " ]," +
// " \"Resource\": [" +
// " \"acs:oss:*:*:com-seaurl-cdn/space\"," +
// " \"acs:oss:*:*:com-seaurl-cdn/space/*\"," +
// " ]," +
// " \"Effect\": \"Allow\"" +
// " }" +
// " ]" +
// "}";
try {
// regionId表示RAM的地域ID。以华东1(杭州)地域为例,regionID填写为cn-hangzhou。也可以保留默认值,默认值为空字符串("")。
String regionId = aliyunOssConfig.getRegion();
// 添加endpoint。适用于Java SDK 3.12.0及以上版本。
DefaultProfile.addEndpoint(regionId, "Sts", endpoint);
// 添加endpoint。适用于Java SDK 3.12.0以下版本。
// DefaultProfile.addEndpoint("",regionId, "Sts", endpoint);
// 构造default profile。
IClientProfile profile = DefaultProfile.getProfile(regionId, AccessKeyId, accessKeySecret);
// 构造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);
request.setPolicy(null); // 如果policy为空,则用户将获得该角色下所有权限。
request.setDurationSeconds(3600L); // 设置临时访问凭证的有效时间为3600秒。
final AssumeRoleResponse response = client.getAcsResponse(request);
System.out.println("Expiration: " + response.getCredentials().getExpiration());
System.out.println("Access Key Id: " + response.getCredentials().getAccessKeyId());
System.out.println("Access Key Secret: " + response.getCredentials().getAccessKeySecret());
System.out.println("Security Token: " + response.getCredentials().getSecurityToken());
System.out.println("RequestId: " + response.getRequestId());
return response;
} catch (com.aliyuncs.exceptions.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 null;
}
}
2、设置跨域支持
如果设置了跨域规则还是不起作用,可以使用下面方式进行修改:
设置跨域规则后调用OSS时仍然报“No 'Access-Control-Allow-Origin'”的错误
上传文件(简单上传和分片上传)
上面配置好权限之后,接下来我们来安装和使用
1、安装ali-oss
yarn add ali-oss
2、初始化oss client
注意:getAcsForUploadFile()
方法就是上面获取sts token
的请求方法
//初始化oss client客户端
async function initOssClient() {
let res = await dispatch(getAcsForUploadFile())
console.log('initOss=', res)
if (res.payload.status === 0) {
const resData = res.payload.data
const client = new OSS({
secure: true,
// yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
region: 'oss-cn-hangzhou',
// 从STS服务获取的临时访问密钥(AccessKey ID和AccessKey Secret)。
accessKeyId: resData.credentials.accessKeyId,
accessKeySecret: resData.credentials.accessKeySecret,
// 从STS服务获取的安全令牌(SecurityToken)。
stsToken: resData.credentials.securityToken,
refreshSTSToken: async () => {
// 向您搭建的STS服务获取临时访问凭证。
const refreshRes = await dispatch(getAcsForUploadFile())
console.log('refreshSTSToken info=', refreshRes)
if (refreshRes.payload.status === 0) {
const refreshResData = refreshRes.payload.data
return {
accessKeyId: refreshResData.credentials.accessKeyId,
accessKeySecret: refreshResData.credentials.accessKeySecret,
stsToken: refreshResData.credentials.securityToken
}
}
},
// 刷新临时访问凭证的时间间隔,单位为毫秒。
refreshSTSTokenInterval: 3000000,
// 填写Bucket名称。
bucket: 'xxx'
});
if (client) {
setOssClient(client)
}
}
}
3、上传文件
// 上传文件前判断单个文件是否超过500mb,如果超过不允许上传
function beforeUploadFile(file, fileList) {
console.log('file=', file)
const isLt500M = file.size / 1024 / 1024 > 500;
if (isLt500M) {
message.warning('超过最大文件上传大小500Mb');
return false
}
return true; // 不调用默认的上传方法
}
// 上传文件状态回调
function onUploadFileChange(info) {
console.log('info=', info)
// 把没有status的文件过滤掉(没有status的文件说明是取消上传的文件)
if (info.file.status) {
setFileTaskDlg({
show: true,
task: info
})
if (info.file.status === 'done') {
dispatch(getFileListByCid({
cid: query.cid
}))
}
if (info.file.status === 'error') {
dispatch(getFileListByCid({
cid: query.cid
}))
}
}
}
// 自定义上传
function uploadFileToOss(options) {
console.log('options=', options)
const {file, onProgress, onSuccess, onError} = options
return new Promise(async (resolve, reject) => {
const filePath = `space/file/${me.name}/${file.name}`
const fileType = getFileType(file.name)
let result = null;
// 判断文件是否超过100mb,如果超过则使用分片上传,否则使用简单上传
if (file.size / 1024 / 1024 > 100) {
console.log('分片上传')
// 分片上传,默认分片1Mb,如果想更改,请参考:https://help.aliyun.com/document_detail/383952.html
result = await ossClient.multipartUpload(filePath, file, {
progress: async (percent) => {
onProgress({percent: percent * 100})
},
}).catch((error) => {
onError(error)
reject(error)
})
} else {
console.log('简单上传')
// 简单上传
result = await ossClient.put(filePath, file, {
progress: async (percent) => {
onProgress({percent: percent * 100})
},
}).catch((error) => {
onError(error)
reject(error)
})
}
await uploadFileCallback(result, {
file,
filePath,
fileType
}, (res) => {
onSuccess(res)
resolve(result)
})
})
}
async function uploadFileCallback(result, data, callback) {
const ossPath = result.res.requestUrls[0].split('?')[0]
const url = ossPath.replace(/^http:\/\//i, 'https://')
const newFileRes = {
status: result?.res?.status,
name: result?.name,
url: url,
}
// 上传成功之后往后台数据库插入一条文件数据
await dispatch(addFile({
fileName: data.file.name,
filePath: data.filePath,
fileSize: data.file.size,
fileContentType: data.fileType,
categoryId: query.cid,
}))
callback(newFileRes)
}
...
beforeUploadFile()
方法是在上传文件之前做自己的业务逻辑处理,比如我这里的超过500mb的文件不允许上传
uploadFileToOss()
是Upload
组件自定义上传规则,所以你不用设置action
等属性
onUploadFileChange()
方法是上传文件时的变化回调,可以通过这个方法设置显示文件上传动态
下载文件(批量下载)
下载文件跟上传差不多,下面示例
function onDownload(d) {
if (selectedRowKeys.length <= 0) {
message.warning('请先选择文件');
} else {
console.log('selectedRowKeys=', selectedRowKeys)
const filterFiles = files.filter(item => selectedRowKeys.includes(item.id))
console.log('filterFiles=', filterFiles)
filterFiles.forEach(item => {
const fileName = item.name
const response = {
'content-disposition': `attachment; filename=${encodeURIComponent(fileName)}`
}
// 填写Object完整路径。Object完整路径中不能包含Bucket名称。
const url = ossClient.signatureUrl(item.path, {response});
const iframe = document.createElement('iframe');
iframe.style.display = 'none';
iframe.style.height = 0;
iframe.src = url;
// 与前两种方式不同,iframe需要挂载到页面上才能触发请求
document.body.appendChild(iframe);
setTimeout(() => {
iframe.remove();
}, 1000);
})
}
}
说明:selectedRowKeys
是我的文件列表选择的文件ids集合item.path
是文件在oss的完整路径,注意:不包含host和bucket-name,如:a/b/c.txt
总结
1、阿里云oss上传文件一开始我使用的是java sdk上传,发现不能在web端分片,于是使用了ali-oss
组件包在浏览器端上传
2、要配置ram权限以及获取sts token还有跨域
引用
js实现单个文件下载,批量下载多个文件
async/await 捕获错误 捕获catch
OSS + Ant Design Upload 网页直传
OSS文档:预览或下载文件
OSS文档