Administrator 1 阅读 面试

分片上传中途失败的解决策略

分片上传中途失败的解决策略(口述版)


面试口述版(优先背这个)

分片上传就是把大文件切成很多小块,一块一块传到服务器,全部到齐后再合并。中间失败很常见,比如网络抖动、浏览器刷新、服务重启、某一片校验失败。

我们的解决策略核心就四个字:断点续传。

具体做法是:

  1. 先初始化上传任务
    前端把文件名、大小、分片大小、文件 MD5(或 hash)发给后端,后端生成一个 uploadId,并记录这个文件一共多少片、哪些片已经成功。

  2. 每片独立上传、独立确认
    每个分片带上 uploadId、分片序号、分片 MD5。上传成功后,服务端把这一片标记为「已完成」,并持久化(Redis 或数据库)。失败只影响当前这一片,不影响已经成功的片。

  3. 失败后不重头传
    刷新页面或重试时,前端先问后端:「这个文件已经传了哪些片?」后端返回已完成的分片列表。前端只补传缺失的那几片。

  4. 超时和脏数据清理
    上传任务设置过期时间,比如 24 小时没完成就清理临时分片,避免磁盘被占满。

  5. 合并前做完整性校验
    所有分片到齐后,按序号合并,再对整个文件做 MD5 校验。校验失败就删除合并结果,保留或重传异常分片,而不是直接当成功。

  6. 并发和重复上传
    同一分片可能被重试两次,服务端要做成幂等:同一 uploadId + 分片序号 已存在就直接返回成功,不要重复写。

一句话总结:
分片状态要落库,失败只重传缺失分片,合并前做整体校验,任务要有过期清理。


完整流程(方便展开)

1. 前端计算文件 hash
2. 调用初始化接口 → 得到 uploadId,以及已上传分片列表(二次上传时)
3. 跳过已上传分片,并发上传剩余分片
4. 每片成功后服务端记录分片完成状态
5. 全部完成后调用合并接口
6. 服务端校验分片数量 + 文件 hash,合并成完整文件
7. 清理临时分片

中间任何一步失败,下次都从第 2 步的「查询已上传分片」继续。


中途失败的典型场景和对策

失败场景 对策
某一片网络超时 只重试这一片,指数退避,限制次数
用户刷新 / 关闭页面 本地记住 file hash + uploadId,再次进入先拉取已传列表
服务重启 分片状态必须落 Redis/DB,不能只放内存
分片写入磁盘失败 该片标记失败,允许重传覆盖
合并时缺片 拒绝合并,返回缺失序号给前端补传
合并后 MD5 不一致 合并失败,记录异常分片或整文件重传
两个客户端同时传同一文件 用文件 hash 秒传或复用 uploadId,分片上传做幂等
任务长期未完成 定时任务清理过期临时文件和记录

服务端需要保存的状态

最少要有这些信息:

  • uploadId
  • 文件 hash、文件名、总大小、分片大小、总分片数
  • 已成功分片序号集合
  • 每个分片的校验值(可选)
  • 过期时间、状态(上传中 / 已合并 / 已取消)

可用 Redis:

upload:{uploadId}           → 任务元信息
upload:{uploadId}:parts     → Set,已成功的分片序号

也可用数据库,更适合对账和过期扫描。


前端配合要点

  1. 分片不要太大也不要太小,常见 2MB~10MB。
  2. 并发上传(比如 3~5 路),但要控制并发,避免打满带宽或打挂服务。
  3. 单片失败重试 3 次,仍失败则记录该片,最后统一补传。
  4. 上传前先用文件 hash 查秒传:服务端已有完整文件就直接返回成功。
  5. 进度条按「已成功分片数 / 总分片数」计算,刷新后也能恢复进度。

口述时可举的例子

「我们项目里大文件(安装包、语料包、视频)走分片上传。初始化时按文件 MD5 生成任务,每片上传成功写入 Redis 的分片集合。如果中途断网,用户再次选择同一文件,前端先用 MD5 换已传列表,只补传缺的片。全部到齐后合并并校验整文件 MD5。任务超过 24 小时未完成会自动清理临时目录。」


和面试官可能的追问

问:为什么不把失败的整文件重新传?
答:大文件重传成本太高,断点续传只补缺失分片,体验和带宽都更好。

问:分片状态放内存行不行?
答:不行,服务重启或多实例下会丢进度。必须 Redis 或 DB。

问:怎么防止重复合并?
答:合并接口做成幂等,状态机从「上传中 → 合并中 → 已完成」,用分布式锁保证同一 uploadId 同时只有一个合并。

问:和 OSS 分片上传的关系?
答:如果直接传阿里云 OSS / S3,可以用它们的 multipart upload:init → upload part → list parts → complete。思路一样,只是状态由对象存储托管。我们自己的策略和 OSS 是同一套思想。


一句话收尾

分片上传中途失败,不要整文件重来,而是:

任务持久化 + 分片幂等 + 按缺失列表续传 + 合并校验 + 过期清理。