必须用 IndexedDB而非localStorage,因其原生支持存储File/Blob对象及元数据;需存文件名、大小、uploadId、已传切片索引数组等;通过change事件存入、页面加载时读取恢复,配合服务端X-Upload-ID实现断点续传。

直接用 IndexedDB 存原始 File 对象 + 上传状态索引,页面刷新后能立刻恢复切片上传,不需要用户重新选文件。
为什么必须用 IndexedDB,不能用 localStorage
localStorage 只能存字符串,而 File 对象包含二进制内容、name、lastModified、type 等不可序列化的属性。JSON.stringify(file) 会丢掉全部文件数据,只剩空对象。IndexedDB 原生支持存储 File 和 Blob,是唯一可行的前端持久化方案。
要存哪些关键信息
- 文件元数据:fileName、fileSize、uploadId(唯一任务标识,可用 crypto.randomUUID() 生成)
- 已成功上传的切片索引数组:如 [0, 1, 2, 4],表示第 0~2 片和第 4 片已传完,第 3 片失败需重试
- 切片大小配置(可选):比如 chunkSize = 5 * 1024 * 1024(5MB),方便恢复时复用相同分块逻辑
写入和读取的典型流程
用户选择文件后立即存入:
- 监听 input[type="file"] 的 change 事件,拿到 event.target.files[0]
- 调用自定义 storeFileAndState(file, uploadId) 函数,把 File 对象和初始状态 { uploadedChunks: [] } 一起写入 IndexedDB 的 objectStore(例如叫 "uploads")
页面加载时自动恢复:
- 初始化时读取 IndexedDB 中所有未完成的 uploadId 记录
- 对每个记录,用 get() 拿回 File 对象,再用 file.slice(start, end) 动态读取尚未上传的片段
- 跳过已成功上传的索引,只发起剩余切片的请求
配合后端实现真正“续传”
前端只管本地状态,续传能力依赖服务端协同:
- 每个切片请求带上 X-Upload-ID 和 X-Chunk-Index 请求头
- 服务端收到后校验该切片是否已存在,避免重复写入
- 上传成功后,前端更新 IndexedDB 中的 uploadedChunks 数组
- 网络中断或页面关闭后,下次打开仍能从断点继续,而不是重头开始


















