IE11跨iframe访问元素触发Script70权限拒绝问题求助
这个问题我之前帮不少开发者踩过坑——IE11对跨iframe的File对象权限管控比Chrome/Firefox严格太多了。核心原因是:当main-iframe跳转后,原页面的File对象关联的上下文被销毁,IE11会直接收回side-iframe对该对象的访问权限,哪怕你之前拿到了引用也没用。下面给你几个可行的解决方案,按推荐优先级排序:
方案1:提前将文件数据转移到side-iframe上下文(最推荐)
既然IE11会在main-iframe跳转后收回File对象权限,那我们就提前把文件的二进制数据转移到side-iframe自己的上下文中,彻底摆脱对main-iframe的依赖。
步骤1:main-iframe中主动传递文件数据
在用户选择文件后,不要等side-iframe来拉取引用,而是主动用FileReader把文件读取成ArrayBuffer,再传给side-iframe:
// main-iframe 中的文件选择事件监听 document.getElementById('fileSelect').addEventListener('change', function(e) { const selectedFile = e.target.files[0]; if (!selectedFile) return; const reader = new FileReader(); reader.onload = function(event) { // 通过top.frames直接调用side-iframe的接收方法 top.frames['sideFrame'].receiveFileData( event.target.result, // 文件的ArrayBuffer数据 selectedFile.name, // 文件名 selectedFile.type // 文件类型 ); }; reader.readAsArrayBuffer(selectedFile); });
步骤2:side-iframe中接收并处理数据
在side-iframe里把收到的ArrayBuffer转换成Blob,这样就能安全调用slice()做分片上传了:
// side-iframe 中定义接收方法 function receiveFileData(arrayBuffer, fileName, fileType) { // 将ArrayBuffer转为Blob,IE11完全支持Blob操作 const fileBlob = new Blob([arrayBuffer], { type: fileType }); // 接下来正常执行分片上传逻辑,这里不会触发权限拒绝 const chunkSize = 1024 * 1024; // 1MB分片 let start = 0; while (start < fileBlob.size) { const end = Math.min(start + chunkSize, fileBlob.size); const chunk = fileBlob.slice(start, end); // 你的AJAX分片上传代码... start = end; } }
优点:彻底脱离main-iframe的上下文依赖,main跳转后完全不影响上传;大文件场景下可以拆分读取再传递,避免内存占用过高。
方案2:保持main-iframe的上下文不销毁
如果不想提前读取整个文件,可以让main-iframe不要做整页跳转,而是用内部嵌套iframe或者pushState的方式加载新内容,维持原页面的上下文。
比如把main-iframe里的跳转逻辑改成:
// 原来的整页跳转:window.location.href = newPageUrl; // 改成用内部iframe加载新内容 function loadNewContent(newPageUrl) { const contentContainer = document.getElementById('mainContent'); contentContainer.innerHTML = ''; // 清空原有内容 const innerIframe = document.createElement('iframe'); innerIframe.src = newPageUrl; innerIframe.style.width = '100%'; innerIframe.style.height = '100%'; innerIframe.frameBorder = '0'; contentContainer.appendChild(innerIframe); }
这样main-iframe的主页面没有刷新,原File对象的上下文一直存在,side-iframe就能继续访问file.slice()了。
优点:不需要修改上传逻辑,只需要调整main-iframe的页面跳转方式;适合超大文件场景,不用提前读取整个文件。
方案3:兼容IE11的Blob.slice语法(辅助优化)
IE11的Blob.slice参数和标准浏览器略有差异(它不支持第三个contentType参数),如果你的上传逻辑需要指定分片的MIME类型,可以加一层兼容封装:
function safeBlobSlice(blob, start, end, contentType) { if (typeof blob.slice === 'function') { try { // 先尝试标准语法 return blob.slice(start, end, contentType); } catch (e) { // IE11不支持第三个参数,降级调用 return blob.slice(start, end); } } // 兼容极旧浏览器(可选) else if (blob.mozSlice) return blob.mozSlice(start, end, contentType); else if (blob.webkitSlice) return blob.webkitSlice(start, end, contentType); throw new Error('当前浏览器不支持Blob分片'); }
内容的提问来源于stack exchange,提问作者The_Mundane

