GTLC全球技术领导力峰会·上海站,首批讲师正式上线! 了解详情
写点什么

客户端直连 S3 实现分片续传思路与实践

2019 年 11 月 15 日

客户端直连S3实现分片续传思路与实践

Amazon S3 是互联网存储解决方案,能让所有开发人员访问同一个具备可扩展性、可靠性、安全性和快速价廉的数据存储基础设施。Amazon S3 提供了一个简单 Web 服务接口,可用于随时在 互联网上的任何位置存储和检索任何数量的数据。开发人员可以利用 Amazon 提供的 REST API 接口,命令行接口或者支持不同语言的 SDK 访问 S3 服务.


同时 S3 对于上传功能的 API 提供也是非常丰富的,与此同时,很多客户对于 S3 的断点续传也有了很深入的需求,本篇博客将会介绍如何使用 S3 的 Javascript SDK 来实现客户端浏览器到 S3 的断点续传功能.


安全考量

首先我们需要度量在浏览器客户端直连上传到 S3 这个场景下的安全问题,我们是一定不能把我们的 AccessKey 暴露到客户端浏览器的,但是上传到 S3 的 API 一定要提供 AccessKey 和 SecretKey,因此这里我们将会利用生成临时的 AccessKey 和 SecretKey(结合有效期)的方式来保证客户端的上传,这里介绍一篇关于利用 TVM (Token Vending Machine)来生成临时 Key 并上传 S3 的文章,本文主要探讨关于 S3 的分片上传和断点续传的知识点.


Javascript SDK 和 S3 API 简介

从整体编程语言架构的层面上来讲,AWS 的各个语言的 SDK 都主要划分为上层和下层的 API, 上层 API 主要是针对一些用户必要的功能利用下层 API 所作的一层封装,掌握了这个原则之后我们就可以合理的利用 AWS 的上层 API 看能否实现自身的需求.


Javascript SDK 文档总结

在掌握 SDK 之前,我们应该先对 SDK 的文档和大致的结构有一个了解,这样才能方便我们更好的使用 SDK, 下面列出了 SDK 的官网入门连接和 API 参考文档.


API 参考文档: http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/index.html


S3 API 参考文档: http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html


构建 SDK 中的 S3 对象

首先,AWS 的 SDK 都是先需要利用 Credentials 来构建对象的,这里我们构建 S3 的对象也是如此,但是请注意一定不能将自己的 Key 暴露在客户端或者提交到代码中,应该使用 TVM 获取了 Key 之后再利用 AWS.Credentials 对象来构建 S3 的对象.



在构建 S3 对象时,也需要同时指定 AWS 的 Region.


利用上层 Javascript API 构建简单的分片断点续传功能

接下来,我们一步一步的来创建上层 API 构建断点续传的实践.


1. 创建工程

这里我们以 node.js 平台的 express 来提供简单的静态服务. 本文不会涉及如何安装 node.js,关于安装指南,可以参考官网 nodejs.org 首先利用 npm 包管理器安装 express 模版生成器:


npm install express-generator -g


完成后我们利用命令行生成项目:


mkdir s3upload


express --view=ejs


这里的--view=ejs主要指定 ejs 作为 express 的 html 模版引擎,方便我们的测试. 创建好之后的工程结构如下图:



  1. 编写页面 UI

  2. ``



这里我们通过引入<script src="https://sdk.amazonaws.com/js/aws-sdk-2.45.0.min.js"></script>来在浏览器端倒入 AWS SDK, 并且我们创建了一个 id 为 progress 的 label 来监控进度. 最后我们引入了/javascript/index.js来编写我们页面的业务逻辑.


分片上传控制

接下来我们在 public/javascript 文件夹中创建 index.js




简单的两个静态文件就能够完成分片上传的功能了.


启动项目

由于 Express 已经建立好模版,只需要在控制台输入 npm start 就能够在 3000 端口监听服务,通过访问 http://localhost:3000 就能够测试分片上传的功能了.


完整的项目代码可以在 Github 上访问.


设置 CORS

由于 SDK 通过 Ajax 提交数据,需要在 S3 桶策略中配置跨域提交的 CORS. 示例中的*建议在生产环境中改成自己的域名.




S3 上层 API 说明

以上实践为大家简单介绍了如何使用 S3 点上层 API 自动完成分片上传的功能,并且通过事件监控的方式来了解上传的进度,这里主要有以下几点需要注意.


1). 上传 api 需要指定 Bucket: ‘testupload’, Key: file.name 让 SDK 识别到桶和文件的 Key 名称.


2). 由于是上层 API, 因此上传程序将会实施自动分片,由于 S3 的最小分片是 5M,所以当文件大于 5M 时此上传程序才会进行自动分片,并且每隔 5M 为一个切片进行上传工作.


3). SDK 使用 AJAX 方式提交自动分片的文件,因此需要设置 S3 的跨域提交配置 CORSRule.


4). 在整个过程中,不要在客户端暴露 AccessKey 和 Secret,利用TVM (Token Vending Machine)一文来安全获取临时 Token.


通过底层 API 来编写实现更多分片上传的功能.

S3 的分片上传主要的原理是通过初始化一次上传的 uploadId, 然后在主动取消或者完成前会一直沿用这个 uploadId,如果用户使用这个 uploadId 持续上传分片则会一直保持该文件的上传,最后通过一个 complete 的操作来结束上传,并且会合并所有分片成为一个文件. 通过上述原理,我们的底层 API 主要会调用以下来实现自定义的分片上传:


1). 首先调用 createMultipartUpload



2). 在返回了 uploadId 之后,将文件切片后利用 uploadPart API 指定在同一个 uploadId 下从第几段开始上传.



3). 最后调用 completeMultipartUpload 结束上传,同时请求成功后 S3 将会自动合并所有分片成为一个文件.



关于各个 API 的详细参数,请参考官方文档.


最后,我们需要注意的是,在整个客户端上传的过程中,难免会有分片并没有全部上传完毕,或者没有最终成功调用了 completeMultipartUpload 的孤儿分片存在,而且随着时间的推移,这些孤儿分片也会越来越多,并且这些没有被 S3 合并的分片,在 S3 的管理控制台中是不可见的,那么我们的最佳实践应该是怎样的呢? 首先我们可以使用 abortMultipartUpload 来取消分片,那么某一次上传没有完成合并的分片将会被清除, 这个可以结合 API 来配合使用.



其次,虽然 S3 控制台中并不会显示未上传完成的孤儿分片,但是我们可以通过 listMultipartUploads 和 listParts 来查看未完成的分片有哪些.



最后,也是最自动的方法是我们可以使用 S3 的桶生命周期 Policy 来设置自动清除和保留未完成合并的孤儿分片的时间周期,让我们并不需要花精力来处理这些异常的情况.


总结

S3 作为轻量简易高可用的存储,结合 AWS 的 SDK,我们在通过临时证书的交互后可以轻易的实现安全的浏览器客户端直接分片断点续传到 S3 的功能,无论是借助于上层的 S3 上传 API 还是利用底层的 createMultipartUpload 实现方式,Javascript SDK 都能够在各个层面给到开发人员灵活轻便的实现这些逻辑,从而让开发人员更专注在自身业务的开发工作中.


作者介绍



李磊


AWS 解决方案架构师,负责基于 AWS 的云计算方案的架构设计,同时致力于 AWS 云服务在国内和全球的应用和推广。在大规模并发后台架构,电商系统,社交网络平台、互联网领域应用,DevOps 以及 Serverless 无服务器架构等领域有着广泛的设计与实践经验。在加入 AWS 之前超过十年的开发和架构设计经验, 带领团队攻克各种技术挑战,总是希望站在技术的最前沿。


本文转载自 AWS 技术博客。


原文链接:


https://amazonaws-china.com/cn/blogs/china/s3-multipul-upload-practice/


2019 年 11 月 15 日 08:00575

欲了解 AWS 的更多信息,请访问【AWS 技术专区】

评论

发布
暂无评论
发现更多内容

产品经理训练营 - 第二次作业

Geek_娴子

GO 进阶学习笔记

zach

go 微服务

产品经理训练营第二章作业——利益相关者

阿波

作业2

YING꯭YING

产品经理训练营第二周总结

happy-黑皮

产品经理训练营

抽奖助手利益相关方和问题分析

June

产品经理训练营

产品思维和产品意识-利益相关方学习总结

mas

第 2 周作业

老元宵

什么是视频?|视频号28天(19)

赵新龙

28天写作

利益相关方以及优先级

skylar

第2章:产品思维总结

让时间说真话

产品经理

年底想跳槽?先想清楚自己要什么。

一笑

工作 28天写作 跳槽面试

GNUCash 4: 我的使用经验

lidaobing

GNUCash 28天写作

产品经理训练营第二次作业

猫。

产品利益相关方小结

skylar

产品经理训练营第二章作业(一)

新盛

第二周作业

正午看星星

极客大学产品经理训练营

你以为阿里真的取消周报了?

Ian哥

28天写作

利益相关方分析-公司及团队维度

梁媛

产品经理

产品经理的书籍清单【持续更新】

sting

产品

第二次作业

Geek_d9dd01

28天瞎写的第二百二十九天:存储过程的故事

树上

28天写作

共识算法的简单理解(二)

石君

28天写作 拜占庭容错 PBFT

作业二

hopeful

极客大学产品经理训练营

抽奖助手stackholder

再见陛下

第二/三周作业

🌴stolmpj

产品经理-第二周作业

LLL777

产品训练营·第二周作业 & 总结

tiu

关于利益相关者的作业

mas

Elasticsearch从入门到放弃:浅谈算分

Jackey

elasticsearch

我用PHP写的第一个Hello world

熊斌

28天写作

DNSPod与开源应用专场

DNSPod与开源应用专场

客户端直连S3实现分片续传思路与实践-InfoQ