为何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
相关产品推荐
相关产品推荐

