iOS断点续上传
该功能将单个文件分割成数个固定大小的块并发上传,可以在实现断点续传的同时加快上传速度(并发上传)。
一、术语
-
上传服务器(Up-Server):提供断点续上传功能的服务器,负责启动新的上传过程、接受上传内容、合并生成最终上传文件。
-
业务服务器(Biz-Server):七牛云存储的客户的业务服务器,负责上传操作鉴权、分配操作策略、生成UpToken、驱动上传端启动上传。
-
上传授权凭证(UpToken):由业务服务器使用AccessKey和SecretKey,对操作策略进行数字签名防伪而生成的上传凭证。参考:生成上传授权凭证
-
操作策略(Policy):由业务服务器填写、由上传服务器执行的操作信息。参考:生成上传授权凭证 4.1. 操作域(Scope):1)空,表示可以上传到任意Bucket(仅限于新增文件);2) “Bucket”,表示限定只能传到该Bucket(仅限于新增文件);3) “Bucket:Key”,表示限定特定的文档,可新增或修改文件; 4.2. 超时时限(DeadLine):上传授权凭证的有效时间,单位是秒; 4.3. 回调URL(CallbackURL):如果指定,在合并文件后,由上传服务器调用此URL,以通知业务服务器做相应处理; 4.4. 返回URL(ReturnURL):如果指定,在合并文件后,由上传服务器重定向到此URL,以通知客户端继续表单处理流程。
-
上传端(Up-Client):七牛云存储的客户的业务终端,负责提出、实施上传。
-
分割块(Block):分割块是以指定大小(一般为4MB)为单位分割待传文件得到的内容块。最后一个分割块可以小于4MB。不同分割块可以乱序并行上传。所有分割块上传完毕后由服务器进行内容排序合并。
-
上传块(Chunk):上传块是对分割块的进一步切分,可以由用户自行设定大小,以适应不同网络环境的限制。上传块必须顺序上传,同时根据需求保存上传过程中的上下文信息、同一分割块已传部分的校验值,以便在断点续传时恢复操作环境。
-
上下文信息(Context):服务器成功保存上传块后返回的操作环境信息,可保存在上传端本地,以便恢复操作环境。上传开始后,每个分割块都有自己的上下文信息。上传端不能修改接收到的上下文信息。
-
校验值(CheckSum):服务器成功保存上传块后返回的、当前分割块的已传部分的校验值,可保存在上传端本地,用于最后合并文件。上传开始后,每个分割块都有自己的校验值。上传端不能修改接收到的校验值。
二、流程
-
请求断点续上传(Request Upload):由上传端发起,向业务服务器申请执行断点续上传;
-
生成操作策略/上传凭证(Make Policy/UpToken):业务服务器对上传端进行鉴权/签名上传凭证/授权;
-
分割文件(Split File):上传端获得授权后,以指定块大小(一般为4MB)为单位,将待传文件分割为数个分割块;
-
上传分割块(Upload Blocks):上传端将单个分割块至上传服务器(可以并发上传不同的分割块,加快上传速度)。每个分割块的上传过程必须顺序完成(串行上传每个上传块)。上传服务器会针对接受到的上传块,返回对应分割块的已上传部分的上下文信息和校验码;
-
合并文件(Make File):所有分割块均成功上传完毕后,由上传端通知上传服务器将其合并成原上传对象文件;
-
若指定CallbackURL,上传服务器在合并文件后会调用此URL,通知业务服务器做相应处理; 否则返回响应结果。
注:在第4步的任何节点均可终止(Abort)上传分割块,或在断点处根据上下文信息恢复上传分割块。
三、API
-
授权
授权信息在 HTTP 头部表现如下:
Authorization UpToken <UploadToken>
授权操作需要在 HTTP Headers 中新增一个名为 Authorization 的字段,并传入 UploadToken 作为值。
上述授权格式等价于:
Authorization UpToken accessKey:authDigest:authInfoEncoded
<UploadToken>
的细节可以参考文档:生成上传授权凭证 -
创建分割块(Block)并上传第一个数据块(Chunk)
HTTP/1.1 POST http://up.qbox.me/mkblk/<BlockSize> Content-Type: application/octet-stream Request Headers: { Authorization: UpToken <UploadToken> } Request Body: <First-Chunk-Binary> HTTP/1.1 200 OK Content-Type: application/json Cache-Control: no-store Response Body: { ctx: <BlockCtx string>, checksum: <BlockChecksum string>, crc32: <ChunkCrc32 int>, host: <SelectedUpHost string> // 后续的 bput, rs-mkfile 等请求要求发到此 host } -
上传分割块(Block)中的数据块(Chunk)
HTTP/1.1 POST <SelectedUpHost>/bput/<BlockCtx>/<Offset> Content-Type: application/octet-stream Request Headers: { Authorization: UpToken <UploadToken> } Request Body: <Next-Chunk-Binary> HTTP/1.1 200 OK Content-Type: application/json Cache-Control: no-store Response Body: { ctx: <BlockCtx string>, checksum: <BlockChecksum string>, crc32: <ChunkCrc32 int>, host: <SelectedUpHost string> } -
合并文件
HTTP/1.1 POST <SelectedUpHost>/rs-mkfile/<EncodedEntryURI>/fsize/<Fsize> \ /mimeType/<EncodedMimeType> \ /meta/<EncodedCustomMeta> \ /customer/<CustomerId> \ /params/<EncodedCallbackParams> \ /rotate/<Rotate> Content-Type: text/plain Request Headers: { Authorization: UpToken <UploadToken> } Request Body: <Ctx-Array> // 以 “,” 分隔的 ctx string 列表,注意 Content-Type: text/plain HTTP/1.1 200 OK Content-Type: application/json Cache-Control: no-store Response Body: { hash: <FileEtag string> }
注意:同一存储空间(Bucket)下,已存在与当前上传条目名称相同的条目时,若当前上传文件内容与原有文件内容一致,则返回成功响应;若文件内容不一致,则上传失败,并返回失败响应。
Fsize
文件大小,单位 Byte,必须项。
表明文件的 MIME 类型,缺省情况下为 application/octet-stream
,可选项。
文件备注信息,可选项,一般不传入。 -
样例
样例程序:
C/C++ - https://github.com/qiniu/c-sdk/blob/master/qbox/up.c
Java - https://github.com/qiniu/java-sdk/blob/master/src/main/java/com/qiniu/qbox/up/UpService.java
Perl - https://github.com/qiniu/perl-sdk/blob/master/lib/QBox/UP.pm
Ruby - https://github.com/qiniu/ruby-sdk/blob/master/lib/qiniu/rs/up.rb
参考资料:
C/C++ SDK 使用指南——断点续上传
七牛云存储