浏览器存储配额与持久化机制 (Browser Storage Quota & Persistence)
浏览器存储配额与持久化机制 (Browser Storage Quota & Persistence):现代浏览器为同源(Same-Origin)提供的客户端离线持久化存储规范(IndexedDB, Cache API, Origin Private File System / OPFS)及其配额管理与防驱逐策略。
核心概念:存储容量与模型上下文解耦
在构建端侧/浏览器内 AI Agent(如端侧 Web 智能体、虚拟文件系统 VFS)时,极易产生一种认知混淆:将大模型的输入上下文窗口(Context Window Token Limit)误当作客户端的存储上限。
- 浏览器存储(Browser Storage):承载静态资产、用户工作区工程文件、文档与音视频。由客户端本地磁盘决定,容量量级在 100MB 至 100GB 之间。
- 模型上下文(Model Context Window):承载 Agent 单次交互时的 Prompt 与 Tool 响应内容。受限于模型注意力机制和 Token 预算(例如 128k ~ 1M tokens)。
解耦原则:
- 存储层放开:IndexedDB 存储限额应当贴合用户本地项目需求(如 128MB ~ 数 GB),单文件放宽至数十 MB。
- 工具层防御(Context Guard):在 Agent 读文件工具(
read_file)中实施守卫,防止读取整个庞大二进制(如 PDF/图片)或巨型文本,仅向模型返回结构化元数据(文件类型、尺寸、大纲)或行切片(Line-slice Truncation),从而既保证浏览器装得下全部资产,又确保模型上下文不被击穿。
浏览器真实配额与驱逐策略 (Quota & Eviction)
| 浏览器内核 / 平台 | 单站 IndexedDB / Cache 上限 | 驱逐机制 (Eviction Policy) | 持久化权限影响 |
|---|---|---|---|
| Chromium / Blink (Chrome, Edge) | 本地可用磁盘空间的 60%(通常可达数十 GB 至上百 GB) | 临时存储模式下,当磁盘空间不足(全局超过 80%)按 LRU 自动清理 | 获得 persistent 授权后免遭自动驱逐 |
| Gecko (Firefox) | 默认约为 2GB 或磁盘空闲的 10%~50%(可按需向用户弹窗申请扩容) | 磁盘紧张时按 LRU 清理非持久化站点 | 获得 persistent 授权后常驻 |
| WebKit (Safari / iOS) | 默认单站约 1GB 左右 | 7 天未使用自动删除(ITP 智能防跟踪与清理策略) | persist() 成功后可豁免 7 天清理 |
关键 Web API
现代标准统一通过 navigator.storage(StorageManager API)进行容量探测与生命周期提升:
1. 动态配额与使用量查询 (estimate)
export interface BrowserStorageEstimate {
quotaBytes: number;
usageBytes: number;
isPersisted: boolean;
}
export async function checkStorage(): Promise<BrowserStorageEstimate> {
if (typeof navigator === 'undefined' || !navigator.storage?.estimate) {
return { quotaBytes: 0, usageBytes: 0, isPersisted: false };
}
const [estimate, isPersisted] = await Promise.all([
navigator.storage.estimate(),
navigator.storage.persisted ? navigator.storage.persisted() : Promise.resolve(false),
]);
return {
quotaBytes: estimate.quota ?? 0,
usageBytes: estimate.usage ?? 0,
isPersisted: Boolean(isPersisted),
};
}2. 持久化存储模式申请 (persist)
浏览器存储默认是 Best-effort(尽力型)。调用 persist() 可以申请切换为 Persistent(持久型):
export async function requestPersistentMode(): Promise<boolean> {
if (typeof navigator === 'undefined' || !navigator.storage?.persist) {
return false;
}
// 某些浏览器(Chrome)基于书签、PWA安装状态、通知授权或访问频次自动放行
// Firefox 通常会向用户弹出权限确认框
return await navigator.storage.persist();
}大文件与二进制资源的高保真渲染方案
在浏览器虚拟文件系统中支持 PDF 等富媒体文件时,有两条渲染路线:
Data URL 模式(反模式):
- 将 Base64 编码直接拼入
<iframe src="data:application/pdf;base64,...">。 - 缺点:大文件(数 MB 以上)会引起页面内存膨胀约 33%,且主流浏览器对导航至高长度 Data URL 存在安全阻断或白屏现象。
- 将 Base64 编码直接拼入
Blob URL 模式(推荐模式):
- 将 Base64 解码为二进制
Uint8Array,封装为new Blob([buffer], { type: 'application/pdf' })。 - 使用
URL.createObjectURL(blob)生成同源引用链接,挂载至原生iframe或<embed>。 - 利用浏览器原生内置的 PDF 查看器(带缩放、目录树、高保真矢量渲染、页码跳转与打印功能),并在组件卸载时及时调用
URL.revokeObjectURL(url)释放内存。
- 将 Base64 解码为二进制
常见坑与排查经验 (Pitfalls)
隐身 / 无痕浏览模式 (Incognito / Private Mode):
- 隐身模式下
navigator.storage.persist()会直接返回false。 - 配额会被大幅度压缩(例如限制在 100MB 或内存临时映射),关闭窗口即全部销毁。
- 隐身模式下
Safari 7 天清理陷阱:
- 若未获得 Persistent 权限,用户超过 7 天未打开该 PWA/网页,Safari 会将整个 Origin 的 IndexedDB 与 LocalStorage 清空。对于重度依赖本地存储的 Web 应用,首屏应当引导用户申请持久化或添加至主屏幕。
Agent 工具上下文击穿:
- 若未对
read_file增加二进制拦截,Agent 会试图把几十万字符的 Base64 塞进 Prompt,瞬间耗尽上下文 Token 配额导致调用失败。务必在 Tool 层面拦截所有非纯文本 MIME 类型。
- 若未对
相关概念
- 低级浏览器底层能力 (Low-Level Capabilities of Modern Browsers)
- PWA (Progressive Web Apps) 与 Web App 全貌
- DOM (Document Object Model 文档对象模型)
本文归档于个人知识库 · 领域:CS & AI · 模块:04 Project_CS_AI/Web