JS实现iframe内嵌PDF自动下载 解决print()仅预览无法下载问题
问题说明
- 页面内嵌id为
conteudoIframe的iframe,加载PDF文档,需要通过JavaScript实现PDF自动下载 - 直接调用JS的
print()方法仅能唤起打印预览,无法触发自动下载 - 引入jsPDF库编写的实现代码未达到预期,原有代码如下:
<iframe id="conteudoIframe" src="目标PDF地址" name="superior" width="100%" height="560px"></iframe> <script> downloadPdfFromIframe(); function downloadPdfFromIframe() { var script = document.createElement('script'); script.src = 'jsPDF库本地引入地址'; document.head.appendChild(script); script.onload = () => { setTimeout(download(), 20000); }; function download() { var myIframe = document.getElementById("conteudoIframe").contentWindow; myIframe.focus(); myIframe.print(); myIframe.close(); var pdf = new jsPDF(); pdf.fromHTML(myIframe); pdf.save('test.pdf'); return false; } } </script>
原有代码问题
- 跨域限制:如果iframe加载的PDF与当前页面不同源,浏览器同源策略会拦截JS对iframe内部
contentWindow内容的读取操作,根本拿不到PDF内容 - API使用错误:jsPDF的
fromHTML()方法作用是将HTML DOM元素转换为PDF,入参需要是HTML节点,不能传入window对象;且该方法无法解析iframe中已经加载完成的原生PDF二进制数据 - 逻辑错误:
setTimeout(download(), 20000)写法会立即执行download()函数,不会等待20秒延迟;myIframe.print()本身是打印逻辑,和下载无关,myIframe.close()也无法触发下载行为
实现方案
同源场景(PDF与当前页面协议、域名、端口完全一致)
不需要依赖jsPDF,直接请求PDF资源生成临时链接触发下载即可,参考代码:
function downloadPdfFromIframe() { const iframe = document.getElementById('conteudoIframe'); const pdfPath = iframe.src; fetch(pdfPath) .then(res => res.blob()) .then(blob => { const blobUrl = URL.createObjectURL(blob); const downloadLink = document.createElement('a'); downloadLink.href = blobUrl; downloadLink.download = '内嵌PDF文档.pdf'; document.body.appendChild(downloadLink); downloadLink.click(); document.body.removeChild(downloadLink); URL.revokeObjectURL(blobUrl); }) } // 等iframe内PDF加载完成后再执行下载逻辑 document.getElementById('conteudoIframe').addEventListener('load', downloadPdfFromIframe);
跨域场景
纯前端没有绕过浏览器同源策略的方法,无法直接实现自动下载,可选解决路径:
- 由后端服务做接口代理,请求目标PDF资源后返回给前端,前端再通过上述blob方式触发下载
- 若可控制PDF服务端的响应配置,给PDF地址添加
Content-Disposition: attachment响应头,浏览器加载该地址时会自动触发下载,不需要额外JS逻辑
内容的提问来源于stack exchange,提问作者Gouveia
相关产品推荐
相关产品推荐

