indexeddb 可稳定存储百 mb 级离线富文本数据,需结构分治(富文本与媒体分离)、二进制直存(blob 替代 base64)、分块控制(每块 200–500kb、短事务写入)及校验兜底(sha-256 校验+wal 日志)。

IndexedDB 可以完整保存离线富文本编辑器中的大体积图文数据,关键在于合理拆分、分块存储、二进制处理与事务控制,而非一次性塞入单条记录。
把富文本结构和媒体资源分离存储
富文本(如 HTML 字符串或 Slate/Quill/ProseMirror 的 JSON state)体积小、结构化强,适合存为 object store 中的普通记录;而图片、视频等二进制资源应转为 Blob 或 ArrayBuffer 单独存入另一个 object store(例如 media),并用唯一 ID 关联。
- 编辑器导出时,先提取所有
<img src="data:image/...">或本地 file 对象,用URL.createObjectURL()或FileReader.readAsArrayBuffer()转成二进制 - 为每个资源生成 UUID,存入
mediastore,主文档中只保留该 UUID 和元信息(如 type、width、height) - 这样避免单条记录超 10MB(部分浏览器 IndexedDB 单条限制较严),也便于按需加载和缓存淘汰
对超长文本做分块写入与增量更新
当编辑内容达数万字或嵌套极深(如带表格、代码块、数学公式),直接序列化为一个 JSON 可能触发内存压力或事务超时。应启用“分块持久化”策略:
- 将文档逻辑切分为段落、区块(block)或“快照版本”,每块控制在 200–500KB 内
- 使用
put()分批写入,每个add()或put()操作包裹在独立短事务中,避免长事务阻塞 UI - 维护一个
version或revisionId字段,在读取时按顺序合并,支持局部更新(比如只改第 3 个区块,就只重写对应 key)
用 Blob 存储图片,避免 base64 膨胀和解析开销
很多编辑器默认把图片转成 data URL(base64),但 base64 比原始二进制大 33%,且每次读取都要 atob() 解码,浪费内存和 CPU。IndexedDB 原生支持 Blob:
- 上传或粘贴图片后,不转 base64,而是直接构造
new Blob([arrayBuffer], {type: 'image/jpeg'}) - 调用
transaction.objectStore('media').put(blob, uuid)—— IndexedDB 会自动流式写入,不加载进 JS 堆 - 渲染时用
createObjectURL()生成临时 URL,或通过get()+URL.createObjectURL(new Blob([result]))动态还原
添加错误恢复与完整性校验机制
离线环境不可靠,写入可能中断。需保障数据可恢复、不损坏:
- 写入前先用
indexedDB.open(..., version)检查 DB 状态;失败时降级到 localStorage 缓存摘要(如最后修改时间、区块 hash 列表) - 对每个区块计算 SHA-256(可用
SubtleCrypto.digest())并连同数据一起存入,读取后校验 hash,不一致则标记“损坏”并触发重同步 - 实现简易 WAL(Write-Ahead Log):新增一个
pending_writesstore,每次写入前先记日志(操作类型、key、timestamp),成功后再删日志;重启时扫描未完成日志重放
不复杂但容易忽略:IndexedDB 不是“本地硬盘映射”,而是带事务语义的异步对象数据库。图文混合场景下,结构分治 + 二进制直存 + 分块控制 + 校验兜底,四者配合才能稳住百 MB 级离线文档。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











