阿里云OSS前端文件上传

前言

https://help.aliyun.com/zh/oss/developer-reference/getting-started-with-oss-sdk-for-browser-js?spm=a2c4g.11186623.0.0.280b5a05QQmhKe

SDK引用

1
2
<!-- 引入在线资源 -->
<script src="https://gosspublic.alicdn.com/aliyun-oss-sdk-6.18.1.min.js"></script>

注意

由于Browser.js SDK通常在浏览器环境下使用,为避免暴露阿里云账号访问密钥(AccessKey ID和AccessKey Secret),强烈建议您使用临时访问凭证的方式执行OSS相关操作。

使用STS临时访问凭证访问OSS

https://help.aliyun.com/zh/oss/developer-reference/use-temporary-access-credentials-provided-by-sts-to-access-oss?spm=a2c4g.11186623.0.0.40e8704cGcJJxb#concept-xzh-nzk-2gb

基本步骤就是

  • 创建用户
  • 用户授予请求AssumeRole的权限
  • 创建角色
  • 创建权限
  • 角色赋予新增的权限

创建用户

  1. 登录RAM控制台

  2. 在左侧导航栏,选择身份管理>用户

  3. 单击创建用户

  4. 输入登录名称显示名称

  5. 访问方式区域下,选择OpenAPI调用访问,然后单击确定

  6. 根据界面提示,完成安全验证。

  7. 复制访问密钥(AccessKey ID和AccessKey Secret)。

重要

RAM用户的AccessKey Secret只在创建时显示,后续不支持查看,请妥善保管。

创建RAM用户后,您需要授予RAM用户通过扮演角色来调用STS服务的权限。

  1. 单击已创建RAM用户右侧对应的添加权限
  2. 新增授权页面,选择AliyunSTSAssumeRoleAccess系统策略。

创建RAM角色

您需要创建RAM角色,用于定义RAM角色被扮演时,可以获得OSS服务的哪些访问权限。

  1. 在左侧导航栏,选择身份管理>角色。

  2. 单击创建角色,选择可信实体类型为阿里云账号,单击下一步。

  3. 在创建角色对话框,角色名称填写为RamOssUpload,选择信任的云账号为当前云账号。

  4. 单击完成。角色创建完成后,单击关闭。

  5. 在角色页面,搜索框输入角色名称RamOssUpload,然后单击RamOssUpload

  6. 单击ARN右侧的复制,保存角色的ARN。

创建权限

  1. 在左侧导航栏,选择权限管理>权限策略

  2. 权限策略页面,单击创建权限策略

  3. 创建权限策略页面,单击脚本编辑,然后在策略文档输入框中赋予角色上传文件到cxzfile的权限。

    具体配置示例如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    {
    "Version": "1",
    "Statement": [
    {
    "Effect": "Allow",
    "Action": "oss:PutObject",
    "Resource": "acs:oss:*:*:cxzfile/*"
    }
    ]
    }
  4. 设置名称为RamOssUploadPolicy

角色授权

为RAM角色RamOssUpload授予自定义权限策略。

  1. 在左侧导航栏,选择身份管理 >角色
  2. 角色页面,找到目标RAM角色RamOssUpload
  3. 单击RAM角色RamOssUpload右侧的新增授权
  4. 添加权限页面下的自定义策略页签,选择已创建的自定义权限策略RamOssUploadPolicy
  5. 单击确定

SDK获取临时凭证

需要的信息有

1
2
3
4
5
6
String endpoint = "sts.cn-qingdao.aliyuncs.com";
// 从环境变量中获取步骤1生成的RAM用户的访问密钥(AccessKey ID和AccessKey Secret)。
String accessKeyId = System.getenv("OSS_ACCESS_KEY_ID");
String accessKeySecret = System.getenv("OSS_ACCESS_KEY_SECRET");
// 从环境变量中获取步骤3生成的RAM角色的RamRoleArn。
String roleArn = System.getenv("OSS_STS_ROLE_ARN");

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.aliyuncs.auth.sts.AssumeRoleRequest;
import com.aliyuncs.auth.sts.AssumeRoleResponse;
public class StsServiceSample {
public static void main(String[] args) {
// STS服务接入点,例如sts.cn-hangzhou.aliyuncs.com。您可以通过公网或者VPC接入STS服务。
String endpoint = "sts.cn-hangzhou.aliyuncs.com";
// 从环境变量中获取步骤1生成的RAM用户的访问密钥(AccessKey ID和AccessKey Secret)。
String accessKeyId = System.getenv("OSS_ACCESS_KEY_ID");
String accessKeySecret = System.getenv("OSS_ACCESS_KEY_SECRET");
// 从环境变量中获取步骤3生成的RAM角色的RamRoleArn。
String roleArn = System.getenv("OSS_STS_ROLE_ARN");
// 自定义角色会话名称,用来区分不同的令牌,例如可填写为SessionTest。
String roleSessionName = "yourRoleSessionName";
// 临时访问凭证将获得角色拥有的所有权限。
String policy = null;
// 临时访问凭证的有效时间,单位为秒。最小值为900,最大值以当前角色设定的最大会话时间为准。当前角色最大会话时间取值范围为3600秒~43200秒,默认值为3600秒。
// 在上传大文件或者其他较耗时的使用场景中,建议合理设置临时访问凭证的有效时间,确保在完成目标任务前无需反复调用STS服务以获取临时访问凭证。
Long durationSeconds = 3600L;
try {
// 发起STS请求所在的地域。建议保留默认值,默认值为空字符串("")。
String regionId = "";
// 添加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(policy);
request.setDurationSeconds(durationSeconds);
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());
} 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());
}
}
}

WEB端上传

ali-oss SDK 是专为 Node.js 环境和浏览器环境设计的,但在小程序环境下可能会遇到兼容性问题。具体来说,微信小程序、支付宝小程序等环境可能会有不同的限制和要求。

npm安装

1
2
npm install ali-oss --save
npm install uuid

示例

这里通过临时凭证进行文件上传

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import { apiCustomGetSts } from '@/assets/api/common_api.js'
import { v4 as uuidv4 } from 'uuid'

function getDateStr() {
const now = new Date()
const year = now.getFullYear()
const month = now.getMonth() + 1
const day = now.getDate()
const formattedMonth = month.toString().padStart(2, '0')
const formattedDay = day.toString().padStart(2, '0')
return `${year}-${formattedMonth}-${formattedDay}`
}

// 引入ali-oss
import OSS from 'ali-oss'
export const ossUploadFile = async (file) => {
let fileName = file.name
fileName = fileName.replace(/[^a-zA-Z0-9_.-]/g, '')
let res = await apiCustomGetSts()
if (res.code === 0) {
let { accessKeyId, accessKeySecret, securityToken } = res.obj
let client = new OSS({
region: 'oss-cn-qingdao', // bucket所在的区域, 默认oss-cn-hangzhou
secure: true, // secure: 配合region使用,如果指定了secure为true,则使用HTTPS访问
accessKeyId: accessKeyId, // 通过阿里云控制台创建的AccessKey
accessKeySecret: accessKeySecret, // 通过阿里云控制台创建的AccessSecret
stsToken: securityToken,
bucket: 'cxzfile', // 通过控制台或PutBucket创建的bucket
refreshSTSToken: async () => {
// 向您搭建的STS服务获取临时访问凭证。
const result2 = await apiCustomGetSts()
if (result2.code === 0) {
let { accessKeyId, accessKeySecret, securityToken } = result2.obj
return {
accessKeyId: accessKeyId,
accessKeySecret: accessKeySecret,
stsToken: securityToken
}
}
}
})
try {
let uuidStr = uuidv4()
// ObjName为文件名字,可以只写名字,就直接储存在 bucket 的根路径,如需放在文件夹下面直接在文件名前面加上文件夹名称
return await client.put(`admin_imgs/${getDateStr()}/${uuidStr}-${fileName}`, file)
} catch (e) {
console.log(e)
}
}
return null
}