Electron中设置Iframe src为blob URL时报ERR_FILE_NOT_FOUND错误
问题产生原因
- 核心诱因:Blob URL 与创建它的 JavaScript 执行上下文强绑定,Blob URL 本质是指向当前上下文内存中 Blob 资源的引用指针,跨上下文无法解析。从报错的
blob:file:///前缀可以判断,你使用的 Blob URL 是在 file 协议上下文(大概率是 Electron 主进程、Preload 脚本等和渲染进程隔离的环境)中生成的,iframe 所属的渲染进程上下文中不存在对应 Blob 资源的映射,访问时自然抛出ERR_FILE_NOT_FOUND错误。 - 设计缺陷:现有实现将 HTML、CSS、JS 拆分为三个独立 Blob 再互相引用,每个独立 Blob 对应唯一的不透明源,即使上下文匹配,也会触发同源策略限制,导致 CSS、JS 资源加载失败。
- 潜在问题:iframe 上通过属性写入的内联
onload脚本会被 Electron 默认的内容安全策略(CSP)拦截,即使 Blob 加载成功,自适应宽高的逻辑也无法执行。
修复方案
- 调整 Blob 生成位置:不要在主进程/Preload 脚本中生成 Blob URL 再通过 IPC 传给渲染进程。如果 HTML/CSS/JS 的原始内容来自主进程,仅通过 IPC 传递纯文本内容到渲染进程,在 iframe 所属的同一个渲染进程上下文中调用 Blob 生成逻辑即可。
- 优化 Blob 生成逻辑,将 CSS、JS 直接内联到 HTML 中,避免跨 Blob 的同源限制,修复后的生成代码如下:
// 注意:该函数必须在加载iframe的渲染进程环境中执行 function getGeneratedPageURL(html, css, js){ const pageContent = ` <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <style>${css}</style> </head> <body> ${html} <script>${js}<\/script> </body> </html> ` // 带上charset参数避免编码异常 return URL.createObjectURL(new Blob([pageContent], { type: 'text/html;charset=utf-8' })) }
注意:拼接脚本时
</script>需要加反斜杠转义为<\/script>,避免和外层脚本标签提前闭合引发语法错误。
- 调整 iframe 加载逻辑,移除内联事件绑定,改用事件监听实现宽高自适应,加载完成后及时释放 Blob 内存,修复后的代码如下:
window.api.receive("render_server", (res) => { res.forEach(res_obj => { // 从IPC传过来的数据中取html、css、js原始文本,不要直接用主进程生成的blob地址 const { html, css, js } = res_obj[0] // 按自身实际数据结构调整字段取值 const pageBlobUrl = getGeneratedPageURL(html, css, js) let box_cont = document.createElement("div"); box_cont.classList.add("box"); let div_frame_overay = document.createElement("div"); div_frame_overay.classList.add("frame_overlay"); div_frame_overay.dataset.dragable = "true"; let i_frame = document.createElement("iframe"); i_frame.setAttribute("frameBorder", 0); // 通过事件监听绑定load逻辑,避免内联脚本被CSP拦截 i_frame.addEventListener('load', () => { const frameDoc = i_frame.contentWindow.document i_frame.style.height = frameDoc.body.scrollHeight + "px" i_frame.style.width = frameDoc.body.scrollWidth + "px" // 加载完成后释放Blob URL占用的内存 URL.revokeObjectURL(pageBlobUrl) }) i_frame.src = pageBlobUrl; box_cont.appendChild(div_frame_overay); box_cont.appendChild(i_frame) document.querySelector(".grid").appendChild(box_cont); }) });
- 校验配置:正常 Electron 默认配置支持 Blob 协议加载,无需额外修改,如果自定义过
webPreferences,确认没有禁用blob:协议的加载权限即可。
内容的提问来源于stack exchange,提问作者unknown
相关产品推荐
相关产品推荐

