在大文件上传的场景中,分片上传(Chunking)、**断点续传(Resumable Upload)**和 MD5 校验是相辅相成的核心技术。它们共同解决了网络波动导致上传失败、服务器超时以及文件完整性校验的问题。


1. 核心流程架构

实现这一机制通常遵循以下逻辑步骤:

第一步:文件分片 (Chunking)

利用 JavaScript 的 Blob.prototype.slice 方法,将一个大文件切割成多个固定大小的数据块(例如每个分片 2MB 或 5MB)。

第二步:生成唯一标识 (MD5)

在上传之前,前端会计算整个文件的 MD5 指纹

  • 作用: 作为文件的唯一 ID,用于实现“秒传”(如果服务器已有该 MD5,直接返回上传成功)和断点续传。
  • 优化: 对于超大文件,全量计算 MD5 会导致浏览器卡死。通常采用增量计算抽样计算(取文件头、尾及中间部分计算)。

第三步:断点续传与秒传

  1. 预检请求: 前端先发送文件的 MD5 到后端。
  2. 后端响应:
    • 秒传: 服务器发现该 MD5 已存在,直接告知上传完成。
    • 断点续传: 服务器返回该文件已上传的所有分片索引(Index)。
  3. 按需上传: 前端过滤掉已上传的分片,只发送缺失的分片。

2. 详细技术实现方案

A. 分片逻辑示例

const CHUNK_SIZE = 5 * 1024 * 1024; // 5MB
let chunks = [];
let cur = 0;
while (cur < file.size) {
  chunks.push(file.slice(cur, cur + CHUNK_SIZE));
  cur += CHUNK_SIZE;
}

B. MD5 计算策略

使用 spark-md5 库。为了不阻塞 UI 线程,建议放在 Web Worker 中运行。

  • 全量: 安全但慢。
  • 抽样: 快速,适用于极大型文件,但有极低概率碰撞。

C. 并发控制

不要同时发起几百个分片请求,这会挤爆浏览器带宽。通常维护一个 Promise 池,限制并发数(如 3-6 个)。


3. 服务器端处理 (Merge)

当所有分片上传完成后,前端发送一个“合并请求(Merge Request)”:

  1. 分片合并: 后端根据 MD5 找到对应文件夹,按索引顺序将分片读入流并写入目标文件。
  2. 完整性校验: 合并后,后端计算文件的 MD5,与前端传来的 MD5 对比。
  3. 清理: 删除临时的分片文件。

4. 异常处理与重试

场景解决方案
网络异常中断前端记录已上传进度,下次上传从预检接口获取起始位置。
单个分片上传失败针对该分片进行 3 次自动重试,失败则停止并提示。
服务器合并压力可以采用“流式合并”或在低峰期异步合并。

总结

  • 分片解决了大文件传输过程中的超时和不稳定性。
  • MD5解决了文件唯一性识别,是秒传和断点续传的“灵魂”。
  • 断点续传通过维护已上传分片列表,极大地提升了用户体验。