Origin Private File System(OPFS,源私有文件系统)
发布于
一句话: 根据 MDN,“origin private file system(OPFS,源私有文件系统)是 File System API 提供的一个存储端点,它私有于页面所在的源,且不像常规文件系统那样对用户可见”,并提供“对其内容的 原地写入访问”。
与用户可见文件系统的区别
Section titled “与用户可见文件系统的区别”MDN 总结了 OPFS 与 File System Access API 所操作的用户可见文件之间的若干区别:OPFS “与其他任何
按源分区的存储机制(例如 IndexedDB API)一样,受浏览器存储配额限制”;可以通过
navigator.storage.estimate() 查看其用量;“清除站点的存储数据会删除 OPFS”;“访问 OPFS 中的文件
不需要权限提示或安全检查”;以及“OPFS 并非设计为对用户可见”。MDN 还指出 OPFS 提供“低层级、逐字节
的文件访问”,并且由于跳过了用户可见 File System Access API 所需的选择器/权限安全检查,“因而速度
更快”。
访问 OPFS 根目录
Section titled “访问 OPFS 根目录”const opfsRoot = await navigator.storage.getDirectory();const fileHandle = await opfsRoot.getFileHandle("my-file.txt", { create: true });MDN 指出:“要首先访问 OPFS,需要调用 navigator.storage.getDirectory() 方法。该方法返回一个
FileSystemDirectoryHandle 对象的引用,代表 OPFS 的根目录。” 在主线程中,文件与目录通过异步、
基于 Promise 的 FileSystemDirectoryHandle.getFileHandle() 与 getDirectoryHandle() 访问,传入
{ create: true } “会在文件或文件夹不存在时创建它”。
在专用 Worker(dedicated Web Worker)中同步访问
Section titled “在专用 Worker(dedicated Web Worker)中同步访问”MDN 解释道,OPFS “还提供了一组同步调用(File System API 的其他调用均为异步)“以提升性能,并且
所返回的 FileSystemSyncAccessHandle “仅能在专用 Worker(dedicated Web Worker)内访问”,从而使
其同步方法不会阻塞主线程执行。尽管名称中带有 “Sync”,MDN 指出”createSyncAccessHandle() 方法
本身是异步的”:
// 在专用 Worker(dedicated Web Worker)内const opfsRoot = await navigator.storage.getDirectory();const fileHandle = await opfsRoot.getFileHandle("fast", { create: true });const accessHandle = await fileHandle.createSyncAccessHandle();
const content = new TextEncoder().encode("Some text");accessHandle.write(content, { at: 0 });accessHandle.flush();accessHandle.close();MDN 列出了返回的 FileSystemSyncAccessHandle 上的同步方法:getSize()(“返回文件的字节大小”)、
write()(“将缓冲区内容写入文件,可选择在给定偏移处写入,并返回已写入的字节数”)、read()
(“将文件内容读取到缓冲区,可选择从给定偏移处读取”)、truncate()(“将文件大小调整为给定
大小”)、flush()(“确保文件内容包含通过 write() 完成的所有修改”)、以及 close()
(“关闭该访问句柄”)。
运行时检测与回退
Section titled “运行时检测与回退”async function openOpfsFile(name) { if (!("storage" in navigator) || !("getDirectory" in navigator.storage)) { // 此处不支持 OPFS——改用 IndexedDB 或内存中存储作为回退方案。 return null; } const opfsRoot = await navigator.storage.getDirectory(); return opfsRoot.getFileHandle(name, { create: true });}MDN 将 OPFS 标记为 Baseline:广泛可用,指出“自 2023 年 3 月起,它已在各浏览器中可用”。MDN
还将其标注为安全上下文特性(“仅在安全上下文(HTTPS)中可用,视支持的浏览器而定”)。同步的
FileSystemSyncAccessHandle 方法则根据 MDN,“仅能在专用 Worker(dedicated Web Worker)内访问”。
- 使用前先做
navigator.storage?.getDirectory特性检测,即便 MDN 将 OPFS 标记为自 2023 年 3 月起 Baseline 广泛可用——较旧或非浏览器环境可能仍不具备它。 - 通过 HTTPS 提供页面;MDN 将 OPFS 记录为仅限安全上下文的特性。
- 仅在专用 Worker(dedicated Web Worker)内使用同步的
FileSystemSyncAccessHandle方法 (read()、write()、flush()、close())——MDN 指出该类“仅能在专用 Worker(dedicated Web Worker)内访问”,以避免阻塞主线程。共享 Worker(shared worker)与 Service Worker 不受支持。 - 记住
createSyncAccessHandle()本身返回一个 Promise,尽管其名称中带有 “Sync”(根据 MDN)。 - 不要指望 OPFS 中的内容对用户可见,也不要指望它能在“清除存储数据”操作后存活——MDN 指出 清除站点存储会删除 OPFS,且它“并非设计为对用户可见”。
- 为浏览器存储配额限制预留余量,因为 MDN 指出 OPFS “与其他任何按源分区的存储机制一样,受 浏览器存储配额限制”。