带sandbox属性的同源iframe中使用PrintJS打印触发跨域如何解决
解决方案
方案1:调整PrintJS调用配置(优先推荐,改动最小)
PrintJS v1.0支持传入配置对象而非直接传入URL,启用弹窗打印模式即可绕过内部iframe的跨域访问限制,你现有的sandbox已经配置了allow-popups,仅需调整调用方式:
// 原调用方式 // printJS('blob:http://localhost:4000/xxx') // 改为配置对象形式 printJS({ printable: '你的blob地址', type: 'pdf', // 根据实际打印资源类型调整,可选值有pdf, html, image, json popup: true // 启用独立弹窗打印,不使用库内部创建的隐藏iframe })
方案2:调整iframe的sandbox属性配置
修正现有sandbox参数的拼写错误,新增弹窗沙箱逃逸权限,配合方案1使用可彻底避免权限拦截:
原错误配置:sandbox="allow-scripts allow-popups allow-modals allow-forms allowdownloads allow-same-origin"
修正后配置:sandbox="allow-scripts allow-popups allow-modals allow-forms allow-downloads allow-same-origin allow-popups-to-escape-sandbox"
说明:原有
allowdownloads拼写错误会被浏览器忽略,修正为标准属性allow-downloads;新增的allow-popups-to-escape-sandbox属性可以让弹窗脱离父iframe的沙箱限制,避免弹窗出现跨域问题。
方案3:全局拦截重写printJS方法(不改动PrintJS源码)
如果方案1不符合需求,你可以在contentApp的入口代码中重写全局printJS方法,替换内部打印逻辑,从根源避免跨frame访问:
// 在contentApp引入PrintJS之后执行以下代码 const originalPrint = window.printJS window.printJS = function (options) { // 兼容原始传参格式 const blobUrl = typeof options === 'string' ? options : options.printable const printType = typeof options === 'string' ? 'pdf' : (options.type || 'pdf') // 自定义创建打印iframe const printIframe = document.createElement('iframe') Object.assign(printIframe.style, { position: 'fixed', right: '-10000px', top: '-10000px', width: '0', height: '0', border: 'none' }) // 给子iframe配置独立沙箱权限 printIframe.sandbox = 'allow-same-origin allow-scripts allow-modals' printIframe.src = blobUrl printIframe.onload = function () { // 同上下文访问不会触发跨域错误 this.contentWindow.print() // 打印完成后自动移除iframe setTimeout(() => document.body.removeChild(printIframe), 1500) } document.body.appendChild(printIframe) }
说明:该方案完全复用你传入的打印参数,没有修改PrintJS的源码文件,仅在全局层面对方法做了拦截重写,符合你的限制条件。
内容的提问来源于stack exchange,提问作者dsi
相关产品推荐
相关产品推荐

