structuredClone() 无法拷贝 FileSystemHandle 对象,会抛出 DataCloneError 异常;因其权限状态不可序列化,应通过 postMessage 传递引用或重新获取 handle。

不能通过 structuredClone() 拷贝具备原始权限的 FileSystemHandle 对象。
FileSystemHandle 不可被 structuredClone() 序列化
FileSystemHandle(包括 FileSystemFileHandle 和 FileSystemDirectoryHandle)是受权限约束的宿主对象,其内部状态(如底层文件系统访问令牌、权限上下文)无法被结构化克隆算法捕获。调用 structuredClone(handle) 会直接抛出 DataCloneError 异常。
- 浏览器明确将
FileSystemHandle列为 structured clone 算法不支持的类型 - 即使 handle 已经获得用户授权(例如通过
showOpenFilePicker()),它仍不具备可序列化的权限凭证 - 克隆操作仅适用于纯数据对象(如 plain objects、arrays、Map、Set、Date、RegExp 等),不延伸至绑定操作系统资源的接口实例
替代方案:传递引用或重新获取 handle
若需在不同上下文(如主线程 ↔ Worker、iframe 间)使用同一文件句柄,应避免拷贝,改用以下方式:
-
跨线程共享引用:通过
postMessage()直接传递 handle(现代浏览器支持将其作为transferable发送,无需克隆) -
持久化权限后重新获取:调用
navigator.storage.getDirectory()或使用handle.resolve()+getDirectoryHandle()等方法,在目标环境中基于已知路径重建访问链 -
存储并复用权限令牌:对已授权的 handle,可调用
self.showDirectoryPicker({id: 'my-app-root'})配合id参数实现“记住位置”,后续用相同id调用showDirectoryPicker()可静默返回已有权限的 handle
注意权限作用域与生命周期
FileSystem API 的权限与具体 origin、top-level browsing context 及用户显式交互强绑定:
- handle 本身不携带可导出的“权限密钥”,无法脱离创建它的页面环境复用
- 关闭标签页或刷新后,未持久化的 handle 将失效;需调用
requestPermission()或再次触发 picker 才能恢复访问 - Worker 中无法直接调用
showOpenFilePicker(),必须由主线程获取 handle 后传入
不复杂但容易忽略:handle 是活的权限代理,不是静态数据——设计时应围绕“传递”和“重获”构建流程,而非尝试复制它。











