【OSS 最佳实践】JS SDK使用STS方式实现断点续传
OSS提供JS SDK方式可以让用户直接在前端页面中嵌入js包直接操作OSS,但是该方式操作OSS最容易出现的问题即是AccessKeyId和AccessKeySecret的泄露导致被恶意访问的情况。因此提供了STS的方式动态获取token操作OSS,随之而来带来了整个业务逻辑的复杂度。今天在这里给大家介绍STS方式进行断点续传的实践方法。
基本概念
1. OSS Javascript SDK
OSS提供了海量、安全、低成本、高可靠的云存储服务,因此该产品最基本的功能即是实现将客户端的资源上传至OSS。OSS底层提供了与平台无关的RESTful API接口,但是该接口需要用户自行实现拼接发到OSS服务器的请求包以及签名参数,对于客户的技术水平提出了较高的要求。
因此OSS提供了各种语言的SDK帮助用户较方便的接入OSS并实现与OSS服务器端的对接操作,详细的SDK列表请参考 OSS SDK 列表,其中绝大多数的SDK均是服务器端的SDK,是无法直接在前端页面中使用的。而Javascript SDK包括浏览器应用和node.js两种方式,浏览器应用即可以实现前端页面直接操作OSS,避免增加应用服务器的负载压力。
2. 断点续传功能
在OSS上传资源的场景中经常会遇到以下场景导致上传失败等问题,对于用户体验较差:
- 上传超过100MB大小的文件;
- 网络条件较差,和OSS的服务器之间的链接经常断开;
- 上传文件需要实时掌握上传进度;
- 业务逻辑需要断点续传。
因此OSS提供了断点续传的方法帮助用户改善该场景。断点续传的方法主要是通过checkpoint和分块上传的接口实现的断点续传。
分块上传是SDK将用户待上传的完整文件分成若干个分片后分别上传,然后上传完成后验证各个分块的etag保证数据正确性后进行合并完成的。因此分块上传的逻辑主要包括:
InitiateMultipartUpload(生成UploadId并设置Object的HTTP头)->UploadPart(上传分块,可并行上传)->CompleteMultipartUpload(根据part列表验证每个part的有效性后合并为完整的Object)。
断点续传即是在progress参数中将断点信息抛出记录在checkpoint变量中。后续续传时即将之前记录的checkpoint信息重新传入multipartUpload接口即可以实现,对应的demo请参考:
var co = require('co');
var OSS = require('ali-oss')
var client = new OSS({region: '<Your region>',accessKeyId: '<Your AccessKeyId>',accessKeySecret: '<Your AccessKeySecret>',bucket: 'Your bucket name'
});
co(function* () {var checkpoint;// retry 5 timesfor (var i = 0; i < 5; i++) {var result = yield client.multipartUpload('object-key', 'local-file', {checkpoint: checkpoint,progress: function* (percentage, cpt) {checkpoint = cpt;}});console.log(result);break; // break if success} catch (err) {console.log(err);}}
}).catch(function (err) {console.log(err);
});
注意:Javascript sdk对于上述的三个部分做了封装,因此对于用户来讲不需要分步操作,而仅需要统一调用multipartUpload接口即可实现。
3. STS的Token功能
OSS SDK均需要通过AccesssKeyId和AccessKeySecret授权后才可以访问OSS,而AccesssKeyId和AccessKeySecret包括三种方式,分别是:
- 主账号AccesssKeyId和AccessKeySecret;
- 子账号AccesssKeyId和AccessKeySecret;
- STS动态生成的AccesssKeyId和AccessKeySecret和AccessKeyToken。
其中前两种方式对应的参数均是固定的,如果直接写在前端页面中会导致泄露的风险导致OSS被恶意操作;而第三种STS动态生成的Token则具有时间戳,仅有在时间戳有效时间内才可以使用。能够提升用户操作安全性。
STS的token一般可以前端代码向应用服务器请求得到结果,也可以使用JS SDK直接操作,demo请参考:
var OSS = require('ali-oss');
var STS = OSS.STS;
var co = require('co');
var sts = new STS({accessKeyId: '<子账号的AccessKeyId>',accessKeySecret: '<子账号的AccessKeySecret>'
});
co(function* () {var token = yield sts.assumeRole('<role-arn>', '<policy>', '<expiration>', '<session-name>');var client = new OSS({region: '<region>',accessKeyId: token.credentials.AccessKeyId,accessKeySecret: token.credentials.AccessKeySecret,stsToken: token.credentials.SecurityToken,bucket: '<bucket-name>'});
}).catch(function (err) {console.log(err);
});
注意:使用STS的token创建OSSClient对象必须同时提供accessKeyId、accessKeySecret和stsToken,否则将报错。
JS SDK使用STS方式实现断点续传
STS的token有时间戳,当超过时间戳会导致后续的请求将无法正常请求,在断点续传时就可能出现当token已经过期后仍然需要上传的操作。为解决该问题我们建议在multipartUpload抛出的yichan异常中获取该异常重新获取token进行续传。最佳实践的代码请参考:
<!DOCTYPE html>
<html>
<head><script src="http://gosspublic.alicdn.com/aliyun-oss-sdk-4.10.0.min.js"></script>
</head>
<body><input type="file" id="uploadFile" /><script type="text/javascript">stsAccessKeyId = ""stsAccessKeySecret = ""stsToken = ""var checkpoint_temp;function multipartUploadWithSts(storeAs, file, cpt) {OSS.urllib.request("http://localhost/sts-server/sts.php", {method: 'GET'}, function (err, response) {if (err) {return alert(err);}try {result = JSON.parse(response);} catch (e) {errmsg = 'parse sts response info error: ' + e.message;return alert(errmsg);}console.log(result)client = new OSS.Wrapper({accessKeyId: result.AccessKeyId,accessKeySecret: result.AccessKeySecret,stsToken: result.SecurityToken,bucket: 'dongchics',endpoint: 'http://oss-cn-hangzhou.aliyuncs.com'});multitest(client, storeAs, file, cpt);})};var upload = function () {var client = null;var file = document.getElementById('uploadFile').files[0];console.log(file);var storeAs = file['name'];console.log("upload file=",file)multipartUploadWithSts(storeAs, file)};function multitest (ossClient, storeAs, file, cpt) {//console.log(file.name + ' => ' + storeAs);var checkpoint_temp;if (cpt) {console.log("multitest with cpt")ossClient.multipartUpload(storeAs, file,{parallel: 2,checkpoint: cpt,progress: function* (percent, cpt) {console.log('Progress: ' + percent);checkpoint_temp = cpt}}).then(function (result) {console.log(result);}).catch(function (err) {console.log(err);multipartUploadWithSts(storeAs, file, checkpoint_temp)});} else {console.log("multitest without cpt")ossClient.multipartUpload(storeAs, file,{parallel: 2,progress: function* (percent, cpt) {console.log('Progress: ' + percent);checkpoint_temp = cpt}}).then(function (result) {console.log(result);}).catch(function (err) {console.log(err);multipartUploadWithSts(storeAs, file, checkpoint_temp)});}};document.getElementById('uploadFile').onchange = upload;</script>
</body>
</html>
这段demo主要包括一下几部分:
1.前端向服务器端发起请求sts的token的请求用户初始化OSSClient对象。而服务器端收到该请求后返回AccessKeyId、AccessKeySecret、SecurityToken和Expiration,这里使用的STS的php sdk实现的,代码可以参考:
<?phpinclude_once 'aliyun-php-sdk-core/Config.php';use Sts\Request\V20150401 as Sts;function read_file($fname){$content = '';if (!file_exists($fname)) {echo "The file $fname does not exist\n";exit (0);}$handle = fopen($fname, "rb");while (!feof($handle)) {$content .= fread($handle, 10000);}fclose($handle);return $content;}$content = read_file('./config.json');$myjsonarray = json_decode($content);$accessKeyID = $myjsonarray->AccessKeyID;$accessKeySecret = $myjsonarray->AccessKeySecret;$roleArn = $myjsonarray->RoleArn;$tokenExpire = $myjsonarray->TokenExpireTime;$policy = read_file($myjsonarray->PolicyFile);$iClientProfile = DefaultProfile::getProfile("cn-hangzhou", $accessKeyID, $accessKeySecret);$client = new DefaultAcsClient($iClientProfile);$request = new Sts\AssumeRoleRequest();$request->setRoleSessionName("client_name");$request->setRoleArn($roleArn);$request->setPolicy($policy);$request->setDurationSeconds($tokenExpire);$response = $client->doAction($request);$rows = array();$body = $response->getBody();$content = json_decode($body);$rows['status'] = $response->getStatus();if ($response->getStatus() == 200){$rows['AccessKeyId'] = $content->Credentials->AccessKeyId;$rows['AccessKeySecret'] = $content->Credentials->AccessKeySecret;$rows['Expiration'] = $content->Credentials->Expiration;$rows['SecurityToken'] = $content->Credentials->SecurityToken;}else{$rows['AccessKeyId'] = "";$rows['AccessKeySecret'] = "";$rows['Expiration'] = "";$rows['SecurityToken'] = "";}echo json_encode($rows);return;
?>
2.在multitest方法中实现断点续传,其中cpt用来判断是否已有断点信息,如果没有该信息则初始分块上传方法,并将断点信息存放在checkpoint_temp变量中;如果有该信息则会将checkpoint_temp作为参数传入multipartUpload方法。
3.在catch异常中重复调用断点续传方法以保证token过期后继续上传。
注意:JS SDK封装的multipartUpload接口实现了并行分块上传,因此当第一个由于token过期出现的403错误后并不会立刻catch到该err,而是需要一段时间才可以捕获该异常,实际测试其延迟在网速正常的情况下为秒级或者分钟级别。
【OSS 最佳实践】JS SDK使用STS方式实现断点续传相关推荐
- MSSQL · 最佳实践 · RDS SDK实现数据库迁移上阿里云RDS SQL Server
title: MSSQL · 最佳实践 · RDS SDK实现数据库迁移上阿里云RDS SQL Server author: 风移 摘要 至今,我们完成了SQL Server备份还原专题系列七篇月报分 ...
- 信创办公--基于WPS的Word最佳实践系列(图文环绕方式)
信创办公–基于WPS的Word最佳实践系列(图文环绕方式) 1. 项目背景 Word中涉及到文字与图片的排版时,各种图片与文字的组合效果,能使页面内容更加清楚.美观,灵活. 2. 打开布局选项中图文环 ...
- 第3.1.1章 WEB系统最佳实践 js控件之slimScroll的使用
漂亮的虚拟滚动条,slimScroll下载地址 $(function() {$(".slimscroll").slimScroll({width: 'auto', //可滚动区域宽 ...
- 蚂蚁区块链第15课 JS SDK概述及API接口速查
1,摘要 本文讲解蚂蚁BAAS的JavaScript SDK概述,说明JS SDK对应的API接口速查.其他语言包SDK参考官网其他章节说明即可. 2,JS SDK 说明 JavaScript SDK ...
- 信创办公--基于WPS的Word最佳实践系列(汇总目录)
信创办公–基于WPS的Word最佳实践系列(汇总目录) 本系列基于WPS的Word进行最佳实践讲解,欢迎大家学习查看哦~ 信创办公–基于WPS的Word最佳实践系列(目录的插入及更新) 信创办公–基于 ...
- 【线上分享】全球多媒体视频内容保护最佳实践
随着后疫情时代教育全面转向线上.短视频和影视剧市场需求增加,音视频平台对于内容保护的重视更是前所未有.国内,5G的加持下,视频的消费蓬勃发展,用户付费习惯养成,如何增加和保护收益,成为各视频平台和在线 ...
- OSS brower js SDK
浅谈 今天带来的是 OSS brower js SDK 的安装过程和使用的 demo 测试用例. 环境准备 OSS brower js SDK 是基于 node js 框架上的服务端程序,服务端启动以 ...
- React.js 2016 最佳实践 徬梓阅读 1584收藏 71
为什么80%的码农都做不了架构师?>>> 译者按:近几个月React相关话题依旧火热,相信越来越多的开发者在尝试这样一项技术,我们团队也在PC和移动端不断总结经验.2016来了 ...
- Node.js CLI 工具最佳实践
为什么写这篇文章? 一个糟糕的 CLI 工具会让用户觉得难用,而构建一个成功的 CLI 需要密切关注很多细节,同时需要站在用户的角度,创造良好的用户体验.要做到这些特别不容易. 在这个指南中,我列出了 ...
- 使用 Node.js Express 的最佳实践
Production best practices: performance and reliability 本文讨论部署到生产的 Express 应用程序的性能和可靠性最佳实践. 这个话题显然属于& ...
最新文章
- SQLServer2005数据库自动备份
- ASP.NET 一般处理程序
- 获取php数组的键名和值
- 算法杂货铺——分类算法之贝叶斯网络(Bayesian networks)
- SQL SERVER大话存储结构(2)
- java csv 导出_java实现CSV文件输出
- CCNP-17 OSPF试验13(BSCI)
- 深入理解socket编程的几个函数和两种fd
- Node.js实现一个HTTP服务器
- python中sorted方法和列表的sort方法使用详解
- 四大门户金融业务接连中招,流量这把钥匙正被氧化
- 基于matlab雷达算法,基于MATLAB的雷达信号处理
- 语音增强论文翻译:2017_SEGAN: Speech Enhancement Generative Adversarial Network
- AECC2015官方破解补丁/AdobeAfterEffectsCC2015中文版免费下载(AE安装教程)
- python-优矿-期权合成期货策略
- David P.Williams论文系列 SAS图像分辨率与目标检测性能的关系
- (附源码)计算机毕业设计SSM旅游分享平台
- Gson系列1 --- Gson 序列化与反序列化 -- 数组 / 集合序列化
- GPS卫星计时周期清零,GPS周期翻转,GPS周期清零
- Kafka 核心原理(贼全面)