阿里云文件上传之客户端上传_阿里云客户端上传文件
阿里云文件上传之前一直是使用服务端上传,但一直存在上传不稳定问题,三兆以上的文件上传经常出现上传超时问题.究其原因客户端将文件上传到业务服务器,然后业务服务器将文件上传到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({// 将设置为OSS Bucket名称。bucket: \"\",// 将设置为OSS Bucket所在地域,例如oss-cn-hangzhou。region: \"\",accessKeyId: \"服务端获取\",accessKeySecret: \"服务端获取\",stsToken: \"服务端获取\" }); const result = client.put(\'qrCode/img/\'+file.name, file); console.log(\"beforeAvatarUpload:\",result);
上传成功后文件访问路径默认就是配置的oss域名+文件存储路径.
补充:断点上传,返回上传进度可配合实现进度条
// 断点续传,阿里云客服提供,可配合实现进度条let savedCpt;const result = client.multipartUpload(\'qrCode/voice/\' + fileInfo.name, fileInfo, {checkpoint: savedCpt,progress: function(p, cpt, res) {//progress is generatorconsole.log(\"p:\", p);this.uploadPercentage = p * 100console.log(\"this.uploadPercentage:\", this.uploadPercentage)console.log(\"cpt:\", cpt);console.log(\"res:\", res);}});
补充:实际场景中会出现连接超时问题,需要进行优化,优化方式就是客户端上传方式优化,由简单上传变更为分片上传.
分片上传场景:
大文件加速上传
当文件大小超过5 GB时,使用分片上传可实现并行上传多个Part以加快上传速度。
网络环境较差
网络环境较差时,建议使用分片上传。当出现上传失败的时候,您仅需重传失败的Part。
文件大小不确定
可以在需要上传的文件大小还不确定的情况下开始上传,这种场景在视频监控等行业应用中比较常见。
分片上传相关代码:
const options = {// 获取分片上传进度、断点和返回值。progress: (p, cpt, res) => {console.log(\"上传进度:\", p);},// 设置并发上传的分片数量。// parallel: 4,// 设置分片大小。默认值为1 MB,最小值为100 KB。partSize: 1024 * 1024,timeout: 120000};await this.client.multipartUpload(\"oss路径+文件名\", file, options).then(res => {console.log(\"res:\", res)}).catch(err => {console.log(2222, err)throw new Error(\"操作失败,请重试!\");})
阿里云官方客户端多文件上传demo