腾讯云 COS 上传
端内文件上传, 之前各个业务都是自己写的上传, 有的是用 PUT
请求, 有的是放在业务POST
请求的 body 中, 对于批量图片上传由于担心上传长时间抢占带宽设置了30 秒强制超时, 对于大文件比如视频上传则是业务自己实现了分片上传, 上传逻辑复杂, 业务自己实现细节繁多, 成功率也不高. 后来切换到了腾讯云的 COS 上传, 图片上传成功率由97.5% 上升至 99.13%, 视频上传成功率由 92.88% 上升到 96.92%. 同时将 COS上传 封装为通用的上传逻辑, 输入支持磁盘文件/内存对象的上传, 输出支持进度以及结果回调, 并额外支持了秒传
/续传
/分片上传
/批量上传
/取消上传
/秘钥续期
/容灾
/结果统计
等能力.
上传架构图总览
模块设计
流程图注释:
四个虚线框 是四个模块
- UploadPackage: 处理批量上传
- UploadTask: 做单个文件的上传
- UploadManager: 是为了保留全局信息 比正在上传文件列表, 以及管理续传信息, 容灾时全局小黑屋等.
- UploadService: 为 UploadPackage 处理秘钥逻辑, 映射关系为 bussID+BucketKey 对应一个 UploadService
上传能力支持
秒传
使用文件 sha1
作为秒传依据.
iOS 处理 sha1
以及 md5
时间对比如下:
sha1 | md5 | |
---|---|---|
视频15s | 0.02s | 0.026s |
视频14min | 0.88s | 2.15s |
视频6.5小时, 文件大小 2.54G | 2.12s | 5.51s |
续传
客户端保留上传过程中的 uploadID
即可uploadID
需要与 桶 Bucket
以及文件 sha1
绑定, 换桶的时候, 原有桶对应的 uploadID 就无用了, 上传失败时候保留 uploadID
, 方便后续续传, 上传成功再清空uploadID
(只是为了清理存储, 没有特殊意义)
桶的定义如下 :
1 | struct BucketInfo{ |
续传信息需要持久化保存
秘钥续期
虽然后台会下发秘钥过期时间, 但是由于客户端时间可能不准, 所以客户端无需自行判定过期, COS SDK 会给过期回调
SDK 遇到秘钥续期的时候会调用下面方法:
1 | /** |
在此回调续期 调用 InitUpload
只用回包的秘钥字段即可.
秘钥要注意的是同一批次请求的秘钥是可以共用的, 但是不同批次的秘钥不能共用, 不同批次的秘钥续期也得分开续期,
比如 第一次上传 ABCD, 后台下发秘钥 1
, 第二次上传EFG, 后台下发秘钥 2
, 那么 ABCD 遇到秘钥过期的时候, 只更新一次 秘钥 1
即可, EFG 秘钥过期就不能用秘钥 1
, 而是得自行更新秘钥 2
.
容灾
业务可以配置主备存储桶, 后台下发多个桶信息; 主桶选择 广州地点
切换备桶的时机. sdk可设置上传进度回调,记录当前进度
失败时如果进度为0, 切换备桶重试
失败时如果进度>0, 不用切换桶, 直接失败, 业务重试之后,可触发断点续传
如果没网络直接报错,不必切换桶
容灾时候如果还有桶可用, 当前桶关15分钟小黑屋, 使用下一个桶进行重试, 如果再无可用桶, 就不用关小黑屋, 直接失败即可.
开始上传的时候, 所有的桶都进了小黑屋的话, 从第一个桶重试, 所有桶重试完直接失败, 无需再关小黑屋.
分片上传
- 文件小于 1M, 直接用
PUT
请求上传即可, - 大于 1M, 先对数据分片, 分片大小为 1M.