阿里云文件上传之前一直是使用服务端上传,但一直存在上传不稳定问题,三兆以上的文件上传经常出现上传超时问题.究其原因客户端将文件上传到业务服务器,然后业务服务器将文件上传到OSS。在这个过程中,一份数据需要在网络上传输两次,会造成网络资源的浪费,增加服务端的资源开销。为了解决这一问题,可以在客户端直连OSS来完成文件上传,无需经过业务服务器中转。下面简单记录一下实现客户端直传的实战过程,本文技术栈:前端vue+后端springbooot.
实现客户端直传需要解决两个问题跨域和oss认证授权信息安全性问题(客户端相对服务端不安全)
首先跨域问题,只需要从oss控制台配置即可,配置规则如下:
无需从代码侧配置(会出现sts权限认证失败问题)
参考文档: 跨域配置
授权信息处理的思路是服务端提供临时授权信息给到客户端.下面是服务端代码:
public static void main(String[] args) {
// 工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考。
// 建议使用更安全的 STS 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/378657.html。
com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
// 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。
.setAccessKeyId("ALIBABA_CLOUD_ACCESS_KEY_ID")
// 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
.setAccessKeySecret("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
// Endpoint 请参考 https://api.aliyun.com/product/Sts
config.endpoint = "stsEndpoint";
com.aliyun.sts20150401.Client client = new Client(config);
com.aliyun.sts20150401.models.AssumeRoleRequest assumeRoleRequest = new com.aliyun.sts20150401.models.AssumeRoleRequest()
.setRoleArn("配置角色权限")
.setRoleSessionName("自定义会话名称");
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
try {
com.aliyun.sts20150401.models.AssumeRoleResponse resp = client.assumeRoleWithOptions(assumeRoleRequest, runtime);
System.out.println("打印内容:"+com.aliyun.teautil.Common.toJSONString(resp));
} catch (TeaException error) {
// 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
// 错误 message
System.out.println(error.getMessage());
// 诊断地址
System.out.println(error.getData().get("Recommend"));
com.aliyun.teautil.Common.assertAsString(error.message);
} catch (Exception _error) {
TeaException error = new TeaException(_error.getMessage(), _error);
// 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
// 错误 message
System.out.println(error.getMessage());
// 诊断地址
System.out.println(error.getData().get("Recommend"));
com.aliyun.teautil.Common.assertAsString(error.message);
}
}
需要的依赖:
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>sts20150401</artifactId>
<version>1.1.4</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>tea-openapi</artifactId>
<version>0.3.2</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>tea-console</artifactId>
<version>0.0.1</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>tea-util</artifactId>
<version>0.2.21</version>
</dependency>
上面给出代码中需要的配置信息参考官方文档针对于客户端上传创建用户并分配权限. 客户端直传创建RAM用户并授权
vue项目中文件上传核心逻辑:
const OSS = require('ali-oss');
const client = new OSS({
// 将<YOUR_BUCKET>设置为OSS Bucket名称。
bucket: "<YOUR_BUCKET>",
// 将<YOUR_REGION>设置为OSS Bucket所在地域,例如oss-cn-hangzhou。
region: "<YOUR_REGION>",
accessKeyId: "服务端获取",
accessKeySecret: "服务端获取",
stsToken: "服务端获取"
});
const result = client.put('qrCode/img/'+file.name, file);
console.log("beforeAvatarUpload:",result);
上传成功后文件访问路径默认就是配置的oss域名+文件存储路径.