You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何使用jQuery print()函数打印在线PDF链接?

解决在线PDF通过iframe打印预览空白的问题

首先,我先帮你排查下代码里的几个明显问题,再针对核心的跨域和加载时机问题给出解决方案:

1. 修复代码语法错误

你的jQuery代码最后少了一组闭合的括号和大括号,这会导致load事件的回调函数根本不会执行!看这里:

$('#print-pdf').load(function () {
    if (navigator.userAgent.indexOf("Firefox") > 0) {
        document.getElementById("print-pdf").contentWindow.print();
    } else {
        document.getElementById("print-pdf").contentWindow.document.execCommand('print', false, null);
    }
// 这里缺失了 }); !!!
});

先把这个语法错误补上,不然后续的逻辑都跑不起来。

2. 核心问题:跨域限制与PDF加载时机

跨域问题

当你加载的在线PDF和你的项目不在同一个域名下时,浏览器的同源策略会阻止你访问iframe的contentWindowcontentDocument对象,这会导致你调用print()时无法正确获取到PDF内容,从而出现空白预览。

PDF加载时机

即使没有跨域问题,iframe的load事件可能在PDF文件下载完成但还没在浏览器中渲染完成时就触发了,这时候调用打印也会得到空白内容。

3. 可行的解决方案

方案一:修正代码并处理加载延迟(仅适合同域或允许跨域的PDF)

先确保PDF所在服务器设置了CORS允许你的域名访问,然后修改代码,给PDF渲染留一点缓冲时间:

var ifrm = document.getElementById("print-pdf");
ifrm.src = 'http://www2.hawaii.edu/~freeman/courses/phil360/16.%20Myth%20of%20Sisyphus.pdf';

$('#print-pdf').on('load', function () {
    // 延迟1秒,给PDF足够的渲染时间(时间可根据实际情况调整)
    setTimeout(function() {
        var iframeWindow = ifrm.contentWindow || ifrm.contentDocument.defaultView;
        try {
            iframeWindow.print();
        } catch (e) {
            // 处理跨域错误
            console.error('打印失败,可能是跨域限制:', e);
        }
    }, 1000);
});

注意:如果服务器没开启CORS,这个方案还是会失败,因为浏览器会阻止跨域访问iframe的内容。

方案二:使用服务器代理(绕过跨域)

如果无法让PDF服务器设置CORS,你可以在自己的服务器上写一个代理接口,把在线PDF的内容转发到同域下,然后让iframe加载这个代理后的URL。比如后端用Node.js写一个简单的代理:

// Node.js 示例(Express框架)
app.get('/proxy-pdf', async (req, res) => {
    const pdfUrl = req.query.url;
    const response = await fetch(pdfUrl);
    const buffer = await response.buffer();
    res.setHeader('Content-Type', 'application/pdf');
    res.send(buffer);
});

然后前端iframe的src改成:/proxy-pdf?url=你的在线PDF地址,这样就变成同域请求了,就能正常访问contentWindow并打印。

方案三:使用PDF.js渲染并打印(最稳定的跨域方案)

PDF.js是Mozilla开发的开源库,可以在浏览器中直接渲染PDF内容,完全绕过iframe的跨域限制,还能更好地控制打印流程。步骤如下:

  1. 引入PDF.js库
  2. 创建一个canvas元素来渲染PDF
  3. 渲染完成后调用打印功能

示例代码:

<!-- 引入PDF.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js"></script>
<div id="pdf-container" hidden></div>

<script>
const pdfUrl = 'http://www2.hawaii.edu/~freeman/courses/phil360/16.%20Myth%20of%20Sisyphus.pdf';
const container = document.getElementById('pdf-container');

// 初始化PDF.js
pdfjsLib.getDocument(pdfUrl).promise.then(pdf => {
    // 渲染所有页面
    const renderPages = async () => {
        for (let i = 1; i <= pdf.numPages; i++) {
            const page = await pdf.getPage(i);
            const viewport = page.getViewport({ scale: 1.5 });
            const canvas = document.createElement('canvas');
            const context = canvas.getContext('2d');
            canvas.height = viewport.height;
            canvas.width = viewport.width;
            container.appendChild(canvas);
            await page.render({ canvasContext: context, viewport }).promise;
        }
        // 所有页面渲染完成后打印
        container.style.display = 'block';
        window.print();
        // 打印后隐藏容器
        container.style.display = 'none';
    };
    renderPages();
}).catch(err => {
    console.error('加载PDF失败:', err);
});
</script>

这个方案不受跨域限制,渲染到canvas后再打印的兼容性和稳定性都更好。

内容的提问来源于stack exchange,提问作者user3140026

火山引擎 最新活动