断点续传核心是「校验→切片→并发上传→合并」四步,每步存取localStorage进度;用fileId唯一标识文件,uploadAllChunks跳过已传切片,并发控制+重试,mergeChunks前校验完整性。

用 async/await 实现多步骤文件切片上传的断点续传,核心是把上传拆成「校验 → 切片 → 并发上传 → 合并」四步,并在每步中保存/读取进度,失败时能从上次中断处继续。
1. 前置:生成唯一文件标识 + 本地记录上传状态
断点续传的前提是能识别“同一个文件”。通常用文件名 + 文件大小 + 文件最后修改时间(或更稳妥的:前端计算文件 hash)生成唯一 key。建议用 spark-md5 或 Web Crypto API 在浏览器端算 chunk 级或 whole-file 级 hash。
上传状态(如已成功上传的切片序号、总切片数、合并是否完成)可存在 localStorage 或 IndexedDB 中。例如:
// 示例 key:fileId = `${fileName}_${fileSize}_${lastModified}`
const uploadState = {
fileId: 'report.pdf_12485732_1712345678900',
uploadedChunks: [0, 1, 3, 4], // 已成功上传的切片索引
totalChunks: 10,
merged: false
};
localStorage.setItem('upload_state_' + fileId, JSON.stringify(uploadState));
2. 切片与并发上传(带重试 + 进度恢复)
使用 async/await 控制异步流程,配合 Promise.allSettled() 容错并发上传,跳过已传过的切片:
说明:
- 先从 localStorage 读取已上传的切片列表,过滤掉已成功的切片
- 对剩余切片调用
uploadChunk()(返回 Promise),每个请求带切片序号、总切片数、文件唯一 ID - 上传失败的切片单独重试(最多 3 次),失败后不阻塞其他切片
- 每次成功后更新
uploadedChunks并存回 localStorage
upload_state_${fileId}3. 单切片上传函数(含服务端校验与幂等)
uploadChunk() 要支持服务端校验:接收切片时检查该切片是否已存在(比如通过 fileId + chunkIndex 查询),若已存在直接返回 success,避免重复上传。前端需在请求头或 body 中带上这些元数据:
-
X-File-ID:文件唯一标识 -
X-Chunk-Index:当前切片序号(从 0 开始) -
X-Total-Chunks:总切片数 -
X-Chunk-Hash(可选):该切片的 md5,用于服务端内容校验
示例请求逻辑(含简单重试):
async function uploadChunk(fileId, index, blob, total) {
const formData = new FormData();
formData.append('chunk', blob, `chunk_${index}`);
formData.append('index', index);
<p>let retry = 0;
while (retry </p><pre class="brush:php;toolbar:false;"> if (res.ok) return await res.json();
throw new Error(`HTTP ${res.status}`);
} catch (err) {
retry++;
if (retry === 3) throw err;
await new Promise(r => setTimeout(r, 1000 * retry)); // 指数退避
}} }
4. 合并切片(仅当所有切片上传完成)
所有切片上传成功后,调用合并接口。为防重复合并,服务端应幂等处理(比如检查 merged 状态或文件是否存在)。前端在合并前再次校验本地状态:
upload_state_${fileId}完整流程可封装为一个可中断/恢复的上传任务:
async function resumeUpload(file) {
const fileId = generateFileId(file); // 自定义生成逻辑
await uploadAllChunks(file, fileId);
await mergeChunks(fileId, file.name);
console.log('上传完成 ✅');
}
用户刷新页面后,调用 resumeUpload(file) 会自动读取 localStorage 中的进度,跳过已传切片,继续后续流程。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











