indexeddb 可直接存储 blob 或 arraybuffer 等二进制数据,但大文件需分块、控制事务并及时释放 url;创建仓库须在 onupgradeneeded 中声明,读写时注意错误处理与内存管理。

IndexedDB 可以直接存储二进制大文件(如图片、视频),但不推荐直接存 Blob 或 ArrayBuffer 到对象仓库中——尤其当文件较大时,容易触发内存压力或事务超时。实际做法是:用 Blob 或 ArrayBuffer 作为值存入,配合合理的分块、事务控制和错误处理。
1. 创建数据库并定义对象仓库
需在 onupgradeneeded 中显式创建支持二进制类型(Blob/ArrayBuffer)的仓库。IndexedDB 原生支持 Blob、Uint8Array、ArrayBuffer 等类型,无需额外编码:
- 使用
indexedDB.open("myDB", 1)打开或新建数据库 - 在
upgradeneeded事件里调用db.createObjectStore("files", { keyPath: "id" }) - 确保不设置
autoIncrement: true(因为 Blob 通常按 ID 或 URL 管理)
2. 存储图片或视频文件(推荐用 Blob)
Blob 更节省内存,适合从 <input type="file"> 或 fetch() 获取的原始文件:
- 获取文件:
const file = input.files[0]; // File 实例即 Blob 子类 - 开启事务:
const tx = db.transaction("files", "readwrite"); - 写入记录:
tx.objectStore("files").add({ id: "img-001", data: file, name: file.name, type: file.type }); - 监听
tx.oncomplete和tx.onerror,避免静默失败
3. 读取并显示图片或播放视频
读出 Blob 后可直接用于 URL 创建或 Canvas 渲染:
- 读取:
const req = store.get("img-001"); - 成功后生成 URL:
const url = URL.createObjectURL(event.target.result.data); - 赋给元素:
img.src = url;或video.src = url; - 注意:每次生成的 URL 需手动释放,否则内存泄漏 —— 在不需要时调用
URL.revokeObjectURL(url)
4. 处理大文件的实用建议
单个文件超过 50MB 时,应考虑分块存储或改用更合适的方案(如 Service Worker 缓存 + Cache API):
- 避免在单个事务中写入多个大 Blob,拆分为多个独立事务
- 对 >10MB 的文件,可先用
File.slice()分片,按 chunk ID 存储,再合并读取(适合自定义流控) - 不要把 base64 字符串存入 IndexedDB —— 它比原始 Blob 大约 33%,且需额外 decode
- 检查浏览器限制:Safari 对 IndexedDB 总容量较保守(常为 50–100MB),Chrome/Firefox 更宽松(可达数 GB,取决于磁盘空间)
不复杂但容易忽略:Blob 存储是“引用式”的,IndexedDB 内部会管理其生命周期;只要事务成功提交,Blob 就持久化,无需额外序列化或转码。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











