You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何postMessage无法传输FileSystemFileHandle?如何修复?

问题:使用postMessage传输FileSystemFileHandle失败的修复方案

使用postMessage传输普通JavaScript对象时正常,但传输FileSystemFileHandle失败,新打开的tab.html页面接收不到数据。MDN文档显示FileSystemFileHandle支持结构化克隆算法,请问该如何修复?


原代码

index.html 中的JavaScript代码

const openButton = document.querySelector('#open'),
  pickerOpts = {
    types: [{
      accept: {
        "text/*": [".txt"],
      },
    }, ],
    excludeAcceptAllOption: true,
    multiple: false,
  }

openButton.addEventListener('click', async() => {
  const handle = await window.showOpenFilePicker(pickerOpts),
    obj = {
      a: 'a'
    },
    tab = window.open('tab.html')
  setTimeout(() => {
    // 无法生效,tab.html接收不到数据
    tab.postMessage(handle, '*')
    // 正常生效
    // tab.postMessage(obj, '*')
  }, 1000)
})

index.html 中的HTML代码

<button id="open">open</button>

tab.html 中的JavaScript代码

window.addEventListener('message', (e) => {
  console.log(e.data)
})

修复方案

问题根源有两个:

  • window.showOpenFilePicker返回的是数组形式的FileSystemFileHandle集合,你直接传递了整个数组;
  • 传输FileSystemFileHandle这类受安全限制的对象时,postMessage不能使用'*'通配符作为目标源,必须明确指定匹配的源。

修改后的index.html JavaScript代码:

const openButton = document.querySelector('#open'),
  pickerOpts = {
    types: [{
      accept: {
        "text/*": [".txt"],
      },
    }, ],
    excludeAcceptAllOption: true,
    multiple: false,
  }

openButton.addEventListener('click', async() => {
  // 取出单个文件句柄(因为multiple设为false)
  const [handle] = await window.showOpenFilePicker(pickerOpts),
        tab = window.open('tab.html')
  
  setTimeout(() => {
    // 使用新标签页的origin作为目标源,确保安全匹配
    tab.postMessage(handle, tab.origin)
  }, 1000)
})

注意:必须保证index.html和tab.html在同一源(相同协议、域名、端口)下运行,跨源场景下无法通过postMessage传输FileSystemFileHandle。


内容的提问来源于stack exchange,提问作者kakakali

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 01:07:51