File System Access API 必须在 HTTPS 或 localhost 下由用户手势触发,调用 showOpenFilePicker() 获取 FileSystemFileHandle 后需 getFile() 读取,createWritable() 写入后必须 close() 才生效。

不能直接用 HTML 标签或属性启用 File System Access API,它必须由 JavaScript 在用户点击等手势下主动调用,且只在 HTTPS 或 localhost 环境生效;window.showOpenFilePicker() 返回的是 FileSystemFileHandle 句柄,不是路径,也不支持自动读同目录其他文件。
必须满足的运行前提条件
API 不是“写了就能用”的功能,环境不合法会直接抛错:
-
SecurityError:页面运行在file://协议下(比如双击打开 HTML 文件),或嵌套在非安全上下文的 iframe 中 - HTTPS 是硬性要求,
http://127.0.0.1也不行,必须是https://或http://localhost - 所有调用必须由用户手势触发,例如
button.onclick、input.onchange,不能在DOMContentLoaded或setTimeout中自动执行 - Chrome/Edge 115+ 原生支持,Firefox 125+ 仅部分支持,Safari 完全未实现——别指望跨浏览器开箱即用
showOpenFilePicker() 之后怎么读内容
拿到句柄只是第一步,fileHandle.getFile() 返回的是只读 File 对象,和 <input type="file"> 的结果一致,不是可写通道:
- 必须显式调用
const file = await fileHandle.getFile()才能读取当前快照 -
file.text()、file.arrayBuffer()、file.stream()都可用,但它们不反映后续外部修改 - 常见错误:误以为
fileHandle本身能直接读,实际必须过getFile() - 若需实时感知文件变更(如被外部编辑器改了),得靠
fileHandle.queryPermission({ mode: 'readwrite' })+ 轮询或监听(目前无原生事件)
createWritable() 写入必须配 close()
这是最常踩的坑:调用了 write() 却没 close(),文件内容为空或残留旧数据:
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
立即学习“前端免费学习笔记(深入)”;
-
const writable = await fileHandle.createWritable()打开的是流式写通道,不是覆盖写入命令 -
await writable.write('hello')只是把数据送进缓冲区,不落盘 - 必须
await writable.close()才真正提交并释放句柄;漏掉这步等于白写 - 追加内容要手动 seek:
await writable.write({ type: 'seek', position: file.size }),API 不提供append模式
如何安全保存而不覆盖误操作
用户点“保存”时,不能无脑复用原始句柄,尤其当文件可能已被外部程序修改:
- 首次打开建议用
showOpenFilePicker({ excludeAcceptAllOption: true }),避免用户误选“所有文件”导致权限过宽 - 保存时优先重用原
fileHandle,但需捕获NotAllowedError(用户取消授权)和NotFoundError(文件被删或移动) - 失败后 fallback 到
showSaveFilePicker()弹新对话框,而不是静默失败 - 句柄不可跨页面持久化存储,但可通过
structuredClone()传给 worker 或存入 IndexedDB(需配合queryPermission检查有效性)
真正麻烦的不是语法,而是权限状态的不确定性:用户可能中途撤销授权、文件可能被锁、句柄可能过期。每次写之前都应检查 await fileHandle.queryPermission({ mode: 'readwrite' }) === 'granted',别假设上次有效这次还有效。


















