腾讯云 COS 上传

腾讯云 COS 上传

端内文件上传, 之前各个业务都是自己写的上传, 有的是用 PUT 请求, 有的是放在业务POST请求的 body 中, 对于批量图片上传由于担心上传长时间抢占带宽设置了30 秒强制超时, 对于大文件比如视频上传则是业务自己实现了分片上传, 上传逻辑复杂, 业务自己实现细节繁多, 成功率也不高. 后来切换到了腾讯云的 COS 上传, 图片上传成功率由97.5% 上升至 99.13%, 视频上传成功率由 92.88% 上升到 96.92%. 同时将 COS上传 封装为通用的上传逻辑, 输入支持磁盘文件/内存对象的上传, 输出支持进度以及结果回调, 并额外支持了秒传/续传/分片上传/批量上传/取消上传/秘钥续期/容灾/结果统计等能力.

上传架构图总览

上传模块客户端逻辑-4

模块设计

流程图注释:
四个虚线框 是四个模块

  1. UploadPackage: 处理批量上传
  2. UploadTask: 做单个文件的上传
  3. UploadManager: 是为了保留全局信息 比正在上传文件列表, 以及管理续传信息, 容灾时全局小黑屋等.
  4. 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
2
3
4
struct BucketInfo{
0 optional string Name; // 后台创建时候保证唯一标志
1 optional string Region; // 桶的地域
};

续传信息需要持久化保存

秘钥续期

虽然后台会下发秘钥过期时间, 但是由于客户端时间可能不准, 所以客户端无需自行判定过期, COS SDK 会给过期回调

SDK 遇到秘钥续期的时候会调用下面方法:

1
2
3
4
5
6
7
/**
获取一个有效的密钥,该密钥可以为临时密钥(推荐),也可以是永久密钥(十分不推荐!!在终端存储是非常不安全的。)。并将获取结果传给调用方。

@param queue 获取密钥的调用方
@param continueBlock 用来通知获取结果的block
*/
- (void)fenceQueue:(QCloudCredentailFenceQueue *)queue requestCreatorWithContinue:(QCloudCredentailFenceQueueContinue)continueBlock;

在此回调续期 调用 InitUpload 只用回包的秘钥字段即可.

秘钥要注意的是同一批次请求的秘钥是可以共用的, 但是不同批次的秘钥不能共用, 不同批次的秘钥续期也得分开续期,
比如 第一次上传 ABCD, 后台下发秘钥 1, 第二次上传EFG, 后台下发秘钥 2, 那么 ABCD 遇到秘钥过期的时候, 只更新一次 秘钥 1 即可, EFG 秘钥过期就不能用秘钥 1, 而是得自行更新秘钥 2.

容灾

业务可以配置主备存储桶, 后台下发多个桶信息; 主桶选择 广州地点
切换备桶的时机. sdk可设置上传进度回调,记录当前进度
失败时如果进度为0, 切换备桶重试
失败时如果进度>0, 不用切换桶, 直接失败, 业务重试之后,可触发断点续传
如果没网络直接报错,不必切换桶

容灾时候如果还有桶可用, 当前桶关15分钟小黑屋, 使用下一个桶进行重试, 如果再无可用桶, 就不用关小黑屋, 直接失败即可.
开始上传的时候, 所有的桶都进了小黑屋的话, 从第一个桶重试, 所有桶重试完直接失败, 无需再关小黑屋.

分片上传

  • 文件小于 1M, 直接用 PUT 请求上传即可,
  • 大于 1M, 先对数据分片, 分片大小为 1M.
-------------本文结束感谢您的阅读-------------

欢迎关注我的其它发布渠道