不能通过FileSystemWritableFileStream直接操作OPFS;前者属File System Access API,需用户授权并面向真实磁盘,后者是无感沙箱虚拟文件系统。

不能通过 FileSystemWritableFileStream 直接操作 Origin Private File System(OPFS)。这是两个完全独立的机制:前者属于 File System Access API,需用户主动授权、面向真实磁盘路径;后者是 OPFS,无弹窗、无权限请求、纯沙箱虚拟文件系统。混淆二者会导致调用失败或 NotAllowedError。
正确区分两种写入场景
File System Access API(带用户手势):适用于“把网络资源保存到用户本地硬盘指定位置”,例如下载大视频、导出报表。必须由点击等用户交互触发 showSaveFilePicker(),拿到 FileSystemFileHandle 后调用 createWritable()。
Origin Private File System(无感沙箱):适用于“在网页内部缓存/加工大文件”,例如离线图像处理、本地解密暂存、AI 模型分片加载。直接调用 window.storage.getDirectory() 即可,无需用户点选。
用 File System Access API 实现网络流直落盘(推荐方案)
这是目前唯一支持 GB 级网络流“零内存缓冲、边下边存”的标准方式,仅 Chromium 102+ 支持:
- 用户点击按钮后调用
showSaveFilePicker()获取目标文件句柄 - 调用
handle.createWritable()得到FileSystemWritableFileStream - 发起
fetch(),将response.body(原生ReadableStream)直接pipeTo(writable) - 不手动
read()/write(),不收集 Blob,不调用arrayBuffer() - 写入完成或中断时,确保捕获异常并调用
writable.close()(否则数据未提交)
用 OPFS 实现网络流暂存(非落盘到用户硬盘)
若目标是“在浏览器内高效缓存下载内容”,而非“保存到用户可见目录”,可用 OPFS:
- 检查支持性:
if ('storage' in window && 'getDirectory' in window.storage) - 获取沙箱根目录:
const root = await window.storage.getDirectory() - 创建文件句柄:
const file = await root.getFileHandle('cache.bin', { create: true }) - 打开可写流:
const writable = await file.createWritable() - 同样用
response.body.pipeTo(writable)写入,最后await writable.close()
⚠️ 注意:OPFS 中的文件对用户不可见,也不能通过系统文件管理器访问,它只供当前 origin 的 JS 读写。
兼容性与降级建议
非 Chromium 浏览器或 HTTP 环境下无法使用上述任一 API:
- 优先检测
'showSaveFilePicker' in window或'storage' in window - 不支持时降级为
Blob + URL.createObjectURL + <a download>,但需控制单次构造的 Blob 大小,避免 OOM - 对超大文件,可引入
stream-saver.js(基于 Service Worker 的流式下载 polyfill)提升体验 - 所有路径操作都必须在安全上下文(HTTPS 或 localhost)中进行


















