IndexedDB可通过分块存储与Range请求实现断点续传:1.建库设计chunks和files仓库,支持二进制块与元数据;2.下载时按Range流式读取并存块、更新进度;3.恢复时查进度与校验,跳过已下部分;4.合成时流式读取拼接Blob供使用。

IndexedDB 本身不直接支持“断点续传”这种网络传输逻辑,但它可以作为客户端持久化存储层,配合 Fetch API 或 XMLHttpRequest 实现大文件的分块下载、校验与续传缓存。核心思路是:把文件切分成固定大小的块(如 1MB),每下载完一块就存入 IndexedDB,并记录已下载偏移量;下次恢复时读取已存块、跳过已下载部分,继续请求剩余范围。
1. 创建支持分块存储的 IndexedDB 数据库
需设计能存二进制块(Blob/ArrayBuffer)和元数据(文件名、总大小、已下载字节、MD5/etag 等)的对象仓库。注意使用 binary 类型字段并启用 autoIncrement 或自定义 keyPath:
- 数据库名建议带版本号(如
fileCache_v2),便于后续升级兼容 - 主对象仓库(如
chunks)keyPath 可设为[fileName, chunkIndex]的复合键,或用字符串拼接("my.pdf_0") - 另建一个
files仓库存整体状态,含fileName(主键)、totalSize、downloadedSize、lastModified、status: "pending" | "paused" | "completed" - 打开 DB 时在
onupgradeneeded中创建仓库并设置 keyPath 和索引(如按 fileName 建索引,方便查询某文件所有块)
2. 下载时按 Range 请求 + 分块写入 IndexedDB
用 fetch() 发起带 Range 头的请求(如 Range: bytes=1048576-2097151),流式读取响应 body 并逐块写入 DB:
- 先查
files仓库确认是否已有该文件及当前进度,计算下一个待请求的start字节位置 - 构造 Request,添加
headers: { "Range": `bytes=${start}-${end}` },注意服务端需支持 CORS 和Accept-Ranges: bytes - 用
response.body.getReader()流式读取,避免一次性加载大 Blob 到内存;每收到一个Uint8Array就暂存到ArrayBuffer缓冲区,满一整块(如 1MB)后调用put()存入chunks仓库 - 每次成功存块后,更新
files中的downloadedSize并 commit(可批量更新减少事务次数)
3. 恢复下载与完整性校验
页面重载或网络中断后,从 IndexedDB 重建下载上下文:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
- 读取
files获取fileName和downloadedSize,再按chunkIndex = Math.floor(downloadedSize / chunkSize)查询对应块是否存在 - 可选做简单校验:对已存每个块计算 SHA-256(用 SubtleCrypto)并与服务端返回的
Content-MD5或预置 manifest 对比;不一致则删除该块重新下载 - 若全部块存在且总大小匹配,可直接触发“合成文件”流程(见下一条);否则从
downloadedSize继续 Range 请求 - 监听
visibilitychange或pagehide事件,在页面退至后台前保存当前进度,降低意外丢失风险
4. 合成完整文件并提供访问
所有块下载完成后,需合并为可用文件(如供 <a download> 或 URL.createObjectURL() 使用):
- 按
chunkIndex升序遍历chunks仓库,用IDBRequest.onsuccess逐个读取 ArrayBuffer,再用new Blob(chunksArray, {type: mimeType})合并 - 注意:不要一次性读取全部块到内存(可能 OOM),可用
cursor.continue()流式读取 +TransformStream或分批Blob拼接(如每 10 块合成一个子 Blob,最后再合并) - 合成后生成
objectURL,绑定到<video>、<iframe>或触发下载;也可将最终 Blob 存入另一仓库(如completedFiles)供离线访问 - 长期缓存建议加 TTL 机制:在
files中存expiresAt时间戳,定期用 IDBKeyRange 查询过期项清理
实际实现中还需处理并发控制(避免同一文件多个下载实例冲突)、磁盘配额超限降级(fallback 到 localStorage 或提示用户清理)、以及 Safari/iOS 对 IndexedDB 的限制(如最大 50MB 默认配额,需用 navigator.storage.estimate() 动态判断)。不复杂但容易忽略细节。

















