FileSystemWritableFileStream是浏览器沙箱内FileSystemAccess API提供的流式写入能力,不限制文件大小但需通过pipeTo()配合ReadableStream分块写入以避免内存溢出,仅Chromium 102+支持。
它不是传统意义上的“文件系统访问”,而是浏览器沙箱内 FileSystemAccessAPI 提供的流式写入能力,专为用户主动授权的目录/文件设计。它本身不限制大小,但实际瓶颈在内存缓冲和浏览器实现:Chrome 当前对单次 write() 调用建议不超过 128MB,否则可能触发 QuotaExceededError 或卡顿。
真正决定能否写大文件的是你是否绕过了全量加载——必须配合 ReadableStream(比如从 fetch 或 File 分块读取)+ pipeTo(),而不是把整个 Blob 一次性 write() 进去。
await writable.write(blob) 大文件 → 极大概率 OOM 或挂起response.body.pipeTo(writable) → 可稳定写 GB 级文件(只要网络/磁盘不中断)showSaveFilePicker(),无法静默调用关键不是“怎么写”,而是“怎么避免把数据全塞进内存”。核心链路是:用户选目标位置 → 获取 FileSystemWritableFileStream → 把源头流(如下载流、加密后流)直接管道过去。
示例场景:从 URL 下载一个 2GB 视频并保存到用户指定位置:
const saveBtn = document.getElementById('save');saveBtn.addEventListener('click', async () => { try { const handle = await window.showSaveFilePicker({ types: [{ description: 'Video', accept: { 'video/*': ['.mp4'] } }] }); const writable = await handle.createWritable(); // ← 这里拿到流 const response = await fetch('https://example.com/large-video.mp4'); await response.body.pipeTo(writable); // ← 关键:零拷贝管道 } catch (err) { console.error(err.name, err.message); }});
createWritable({ keepExistingData: true }) 可续传(需自行管理 offset,不推荐初用)TransformStream 插入管道:response.body.pipeThrough(decrypter).pipeTo(writable)
read()/write() —— pipeTo() 已内置背压控制,手动做反而易出错最常遇到的不是语法错,而是权限与生命周期问题:
NotAllowedError:没在用户手势中调用 showSaveFilePicker(),或用户点了取消 → 必须确保是 click/tap 后立即调用SecurityError:页面非 HTTPS 或 iframe 没加 allow="filesystem" 属性 → 检查协议和 iframe sandboxTypeError: Failed to execute 'pipeTo' on 'ReadableStream':目标流已关闭或被其他操作使用 → 确保 writable 未被提前 close() 或 abort()
目前仅 Chromium 102+ 原生支持(Edge 同步),Firefox 和 Safari 完全不支持。别指望 polyfill —— 这是底层平台能力,不是 JS 库能模拟的。
更隐蔽的限制在于操作系统集成:
pipeTo() 写入,表现为卡在 99% 或静默失败 → 需提示用户临时关闭实时防护FileSystemAccessAPI 无效,它走的是独立的沙箱文件句柄,无需额外授权showSaveFilePicker(),只能退化为 a[download] 或 URL.createObjectURL()(受限于 Blob URL 生命周期)真正难的从来不是 API 调用,而是处理用户取消、网络中断、磁盘满、权限弹窗被广告拦截器屏蔽这些现实情况——它们不会抛出标准错误,只会让 pipeTo() 悄悄停住。