indexeddb 可高效存储大文件分片校验和,通过 chunkchecksums object store(主键为 "${fileid}_${chunkindex}")、fileid 索引及事务隔离实现快速查重、批量校验与清理。

IndexedDB 可以高效存储大文件分片的校验和(如 SHA-256 或 MD5),避免每次上传前重复计算。关键在于:用 Object Store 存储分片元数据(含分片 ID、文件 ID、校验和、大小、状态),并配合 事务隔离 和 键范围查询 快速校验已上传分片。
设计合理的 Object Store 结构
创建一个名为 chunkChecksums 的 Object Store,主键设为复合键或自定义 keyPath:
- 推荐用
id作为主键,格式为"${fileId}_${chunkIndex}"(如"abc123_0"),便于精确查找和批量清理 - 存储字段包括:
fileId、chunkIndex、checksum(字符串,如 hex 或 base64)、size、uploadedAt(时间戳)、status("pending" / "uploaded" / "failed") - 添加一个
fileId索引,支持按文件批量读取或删除所有分片记录
写入分片校验和(带错误防护)
计算完单个分片的校验和后,用只读事务检查是否已存在;若不存在,再用读写事务写入:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
// 示例:保存单个分片校验和
function saveChunkChecksum(fileId, chunkIndex, checksum, size) {
return new Promise((resolve, reject) => {
const db = indexedDB.open("uploadCache", 1);
db.onsuccess = () => {
const tx = db.result.transaction("chunkChecksums", "readwrite");
const store = tx.objectStore("chunkChecksums");
// 先查重(避免重复写)
const key = `${fileId}_${chunkIndex}`;
const getRequest = store.get(key);
getRequest.onsuccess = () => {
if (getRequest.result) {
resolve("already exists");
return;
}
// 写入新记录
const record = { id: key, fileId, chunkIndex, checksum, size, uploadedAt: Date.now(), status: "pending" };
const addRequest = store.add(record);
addRequest.onsuccess = () => resolve();
addRequest.onerror = () => reject(addRequest.error);
};
getRequest.onerror = () => reject(getRequest.error);
};
});
}
上传前快速校验已缓存分片
构造待上传分片列表时,用 IDBKeyRange.bound 批量查询同一文件的所有分片记录,比逐个 get 更快:
- 用
index.getAll()获取该文件全部分片元数据(支持游标遍历,适合几千分片) - 对比本地新计算的校验和与 DB 中存储值,跳过匹配项,仅上传不一致或缺失的分片
- 对失败分片可标记
status: "failed",后续重试时优先处理
清理与维护策略
避免缓存无限增长:
- 上传成功后,调用
store.delete(IDBKeyRange.bound(`${fileId}_0`, `${fileId}_99999`))清理整组分片 - 定期用
indexedDB.deleteDatabase()或按uploadedAt索引清理 7 天前的 pending 记录 - 监听
upgradeneeded处理 schema 迭代(如新增字段或索引)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










