以下列出在 夺目 产品的开发中,对 WebStorage 和 IndexedDB 使用的一些经验。
WebStorage 存储空间限制
首先,存储分为两种:
- 临时存储 (Temporary Storage),默认类型,之后可能会被浏览器删除。
- 持久存储 (Persistent Storage),不会被浏览器自动删除,可以使用 StorageManager::persist() 方法将此域名的存储类型转为持久型,此时浏览器会弹出弹窗征求用户许可,用户也可以选择拒绝。
根据 MDN 的文档,浏览器分配给数据存储的磁盘空间大小是动态的,会根据磁盘剩余空间决定,同时对于一个具体域名下的空间分配也有一定策略。
Firefox 的策略为:
- 全局限制 (Global Limit),50% 剩余磁盘空间
- 域名组限制,大约是 20% 的全局限制量。例如
mozilla.org
/joe.blogs.mozilla.org
/firefox.com
被认为是同一个域名组,共享一个组限制。
当磁盘空间告罄,quota manager 会开始删除临时存储 (temporary storage),以域名为单位删除,直到觉得磁盘空间余量尚足。
删除顺序遵循 LRU 原则,最后访问时间距离现在最远的域名下的 object store 会被整个删除。
目前 chrome (79) 的策略细节可能不太一样,但还没有找到具体文档描述。
查询当前存储空间状况
使用 StorageManager::estimate() 方法查询当前存储空间的配额 (quota) 和已使用量 (usage)。
详细描述在 Stroage 草案 中可查。
|
额外一说,在 Chrome 中返回的 estimate 还会多出一个非标准字段 usageDetails
,能看到更详细的信息。
|
实际使用时,一些技术选择考量
存储大文件和数据块
IndexedDB 在 WebApp 中可以担任数据持久层,比起更早的基于字符串的 LocalStorage ,可以存储更复杂、更多样化和更大的数据。以下是一些常见的场景:
- ArrayBuffer/Uint8Array/Float32Array 存储等二进制数据和视图对象,用作密集计算
- ImageData 在基于 canvas 的绘图程序或游戏中做绘制结果缓存
- File/Blob 文件分片上传,大文件存储
Blob 与常用二进制数据类型互转
如果文件很大,建议使用 File/Blob,目前在 mac chrome 79 上测试,保存包含 ArrayBuffer 的单条记录超过 100MB,便会写入失败。
使用 Blob(或者基于它的 File 对象) 还有许多好处,如果应用的主要功能是音视频相关处理,使用 URL.createObjectURL(blob)
生成的字符串最后能直接作为原生 DOM 的 img/video/audio 标签接受的 src。而且 blob.type
是有意义的 MIME Type,在调试数据的时候也有更多的信息。因此 Blob 很适合作为处理后可以直接展示的成品存储。
但若数据需要被修改和操作,Blob 需要转化为 ArrayBuffer 以及具体的类型数据视图 Uint8Array 等使用。
Blob -> ArrayBuffer
以下两种方法,都为异步过程
1 使用 blob.arrayBuffer() 方法。此方法为标准的推荐,不过目前浏览器支持有限。
|
2 使用 FileReader
|
ArrayBuffer -> Blob
同步过程
|
参考
https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Browser_storage_limits_and_eviction_criteria
https://developers.google.com/web/updates/2016/06/persistent-storage
https://developer.chrome.com/apps/offline_storage
https://stackoverflow.com/questions/17809824/how-to-use-navigator-instead-of-window-webkitstorageinfo-html5-file-system-api