分片下载不直接生成MD5,校验在下载完成拼接后或边下边验:下载完所有分片→拼成完整ArrayBuffer/Blob→Web Worker异步计算整体MD5→比对服务端提供的可信MD5值。

分片下载本身不直接生成 MD5,校验发生在**下载完成拼接后**或**边下边验**两种模式。所谓“异步校验 MD5”,本质是:下载完所有分片 → 拼成完整 ArrayBuffer 或 Blob → 在后台线程(Web Worker)中异步计算整体 MD5 → 与服务端提供的预期值比对。不能在主线程同步算,否则页面卡死。
先确保服务端提供可信的 MD5 值
服务端必须在返回分片元数据时,一并下发该文件的完整 MD5(如通过响应头 X-File-MD5,或响应体字段 fileHash)。这个值是校验基准,不可由前端自行推导或省略。
- 推荐放在首次请求(如
GET /api/file/info?id=123)的响应中,避免额外 round-trip - 若服务端只支持分片接口(如
GET /api/file/chunk?fid=123&index=0),需约定在首个分片响应头中携带完整 MD5 - 切勿用各分片 MD5 拼接后再哈希——这和标准 MD5 不等价,服务端必须用相同逻辑(即全量字节流 hash)生成
下载完成后拼接再校验(推荐,逻辑清晰)
这是最常见、最稳妥的做法:等所有分片 fetch 成功,按序合并为一个 Uint8Array,再交给 Web Worker 异步算 MD5。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 用
Promise.all(chunksPromises)确保全部分片到位,避免漏片或乱序 - 拼接示例:
const totalLength = chunks.reduce((sum, buf) => sum + buf.byteLength, 0); const fullArray = new Uint8Array(totalLength); let offset = 0; chunks.forEach(buf => { fullArray.set(new Uint8Array(buf), offset); offset += buf.byteLength; }); - 把
fullArray.buffer传给 Worker(结构化克隆安全),Worker 内用SparkMD5.ArrayBuffer计算,完成后postMessage({ md5 }) - 主线程监听
worker.onmessage,比对结果,失败则提示“文件损坏”而非“网络错误”
边下载边校验(适合超大文件 + 内存敏感场景)
不等全部下载完,而是每收到一个分片就 append 到 SparkMD5 实例中——但必须保证分片严格按序接收,且不能跳片或重试乱序。
立即学习“Java免费学习笔记(深入)”;
- 适用前提:分片接口支持按序阻塞式拉取(如
index=0必须先完成,才发index=1),或你有强序控制逻辑 - 主线程内即可做(无需 Worker),因每次只处理几 MB 的 ArrayBuffer,开销小:
spark.append(new Uint8Array(chunkArrayBuffer)) - 全部分片回调结束后调用
spark.end()得到最终 MD5,立即比对 - 注意:若某分片下载失败后重试,必须确保重试内容与原分片字节完全一致(服务端需幂等),否则 MD5 失效
测试要点:覆盖异常与边界
真正可靠的测试不是只跑通正常流程,而是验证校验机制能否捕获问题:
- 手动篡改某一分片 ArrayBuffer 的任意一个字节(如
uint8[0] ^= 1),确认最终 MD5 不匹配 - 故意跳过一个分片(不 push 到 chunks 数组),看拼接后长度不足 + MD5 错误
- 用极小文件(如 1KB)和极大文件(如 2GB 模拟)分别测试,验证分片逻辑和 Worker 内存行为是否稳定
- 在 Worker 中抛出异常(如
throw new Error('md5 fail')),检查主线程能否正确捕获并降级处理 - 对比服务端返回的 MD5 和本地计算值,建议转为小写统一比较(避免大小写差异误判)

















