直接从 JavaScript 打印 PDF
Posted
技术标签:
【中文标题】直接从 JavaScript 打印 PDF【英文标题】:Print PDF directly from JavaScript 【发布时间】:2013-04-20 19:25:24 【问题描述】:我正在构建一个 html 格式的 PDF 列表。在列表中,我想包括一个下载链接和一个打印按钮/链接。有什么方法可以直接打开 PDF 的“打印”对话框,而无需用户查看 PDF 或打开 PDF 查看器?
将 PDF 下载到隐藏的 iframe 并触发它使用 javascript 打印的一些变体?
【问题讨论】:
【参考方案1】:基于下面的 cmets,它不再适用于现代浏览器 这个问题展示了一种可能对您有帮助的方法:Silent print an embedded PDF
它使用<embed>
标签将PDF嵌入到文档中:
<embed
type="application/pdf"
src="path_to_pdf_document.pdf"
id="pdfDocument"
/>
然后在加载 PDF 时在 Javascript 中对元素调用 .print()
方法:
function printDocument(documentId)
var doc = document.getElementById(documentId);
//Wait until PDF is ready to print
if (typeof doc.print === 'undefined')
setTimeout(function()printDocument(documentId);, 1000);
else
doc.print();
您可以将嵌入嵌入到隐藏的 iframe 中并从那里打印出来,从而为您提供无缝体验。
【讨论】:
此解决方案不起作用...我的 Chrome FF 权限被拒绝 如果嵌入的文档位于不同的域中,这将不起作用。 更容易将 javascript 添加到 pdf 以在呈现时打印。这就是谷歌文档所做的。这种方式要么是浏览器加载并打印它,要么是 adobe 插件。 是的,我在所有未定义 print() 方法的浏览器上都遇到了这个问题。这种方法过时了吗?还有其他解决方案吗? 这不再有效。 Chrome 最新版本,同一域上的 PDF。 @nullability 如果您找不到解决方法,请进行编辑并明确说明所写的内容在过去是正确的,但不再有效,这样人们就不会浪费时间尝试了。【参考方案2】:这是一个从 iframe 打印 PDF 的功能。
您只需将 PDF 的 URL 传递给函数。加载 PDF 后,它将创建一个 iframe 并触发打印。
请注意,该函数不会破坏 iframe。相反,它会在每次调用函数时重用它。很难销毁 iframe,因为在打印完成之前需要它,并且 print 方法没有回调支持(据我所知)。
printPdf = function (url)
var iframe = this._printIframe;
if (!this._printIframe)
iframe = this._printIframe = document.createElement('iframe');
document.body.appendChild(iframe);
iframe.style.display = 'none';
iframe.onload = function()
setTimeout(function()
iframe.focus();
iframe.contentWindow.print();
, 1);
;
iframe.src = url;
【讨论】:
谢谢你,因为你帮我解决了一个大问题:没有setTimeout
,打印功能有时会失败。不知道为什么,希望有人能找出来。
print 方法确实有回调支持,但是当你在 2014 年写这个答案时它还没有得到广泛的支持。不过现在是;所有主要桌面浏览器的最新版本都支持onafterprint
。我有点担心重用 iframe 可能会引入竞争条件,即有人快速单击两个按钮并最终打印第二个 PDF 两次,因为在第一个打印对话框出现之前 iframe URL 已经被换掉。
如果 iframe 内容不是来自同一来源,Chrome 会阻止 .print() 方法。不幸的是,截至 2021 年无法使用【参考方案3】:
您可以使用 Print.js (npm install print-js
)。解压后为 128kB,您可以在 http://printjs.crabbly.com/ 找到文档。
但它不能在 IE 上打印,在这种情况下,您必须下载 PDF。
$http(
url: "",
method: "GET",
headers:
"Content-type": "application/pdf"
,
responseType: "arraybuffer"
).success(function (data, status, headers, config)
var pdfFile = new Blob([data],
type: "application/pdf"
);
var pdfUrl = URL.createObjectURL(pdfFile);
//window.open(pdfUrl);
printJS(pdfUrl);
//var printwWindow = $window.open(pdfUrl);
//printwWindow.print();
).error(function (data, status, headers, config)
alert("Sorry, something went wrong")
);
【讨论】:
不在 IE、Edge 或 Firefox 上打印 PDF。 今天尝试使用 jQuery get 从服务器获取 pdf 的字节,然后如上所述创建 blob 和“createOvjectURL”。在这种情况下,PrintJS 不会显示打印对话框。 :) 我可以单击打印多个pdf文件吗? 刚刚尝试了演示页面。它在 Firefox 中打印【参考方案4】:https://github.com/mozilla/pdf.js/
现场演示http://mozilla.github.io/pdf.js/
这可能是你想要的,但我看不出这有什么意义,因为现代浏览器包含这样的功能,而且它在低功率设备上运行非常慢,比如移动设备,顺便说一下,有自己的优化插件和应用程序。
【讨论】:
Pdf.js 在打印大文档时也非常慢,比如 80MB+【参考方案5】:我使用此功能从服务器下载pdf流。
function printPdf(url)
var iframe = document.createElement('iframe');
// iframe.id = 'pdfIframe'
iframe.className='pdfIframe'
document.body.appendChild(iframe);
iframe.style.display = 'none';
iframe.onload = function ()
setTimeout(function ()
iframe.focus();
iframe.contentWindow.print();
URL.revokeObjectURL(url)
// document.body.removeChild(iframe)
, 1);
;
iframe.src = url;
// URL.revokeObjectURL(url)
【讨论】:
【参考方案6】:从base64字符串打印pdf的跨浏览器解决方案:
Chrome:打印窗口已打开 FF:带有 pdf 的新标签页已打开 IE11:打开/保存提示已打开.
const blobPdfFromBase64String = base64String =>
const byteArray = Uint8Array.from(
atob(base64String)
.split('')
.map(char => char.charCodeAt(0))
);
return new Blob([byteArray], type: 'application/pdf' );
;
const isIE11 = !!(window.navigator && window.navigator.msSaveOrOpenBlob); // or however you want to check it
const printPDF = blob =>
try
isIE11
? window.navigator.msSaveOrOpenBlob(blob, 'documents.pdf')
: printJS(URL.createObjectURL(blob)); // http://printjs.crabbly.com/
catch (e)
throw PDFError;
;
printPDF(blobPdfFromBase64String(base64String))
奖励 - 在 IE11 的新选项卡中打开 blob 文件
如果您能够在服务器上对 base64 字符串进行一些预处理,您可以在某个 url 下公开它并使用printJS
中的链接:)
【讨论】:
【参考方案7】:@Nicolas BADIA 回答的简化:
function printPDF (url)
let pdfFrame = document.body.appendChild(document.createElement('iframe'));
pdfFrame.style.display = 'none';
pdfFrame.onload = () => (void pdfFrame.contentWindow.print());
pdfFrame.src = url;
【讨论】:
【参考方案8】:您可以使用fetch
下载pdf文件,并使用Print.js进行打印
fetch("url").then(function (response)
response.blob().then(function (blob)
var reader = new FileReader();
reader.onload = function ()
//Remove the data:application/pdf;base64,
printJS(
printable: reader.result.substring(28),
type: 'pdf',
base64: true
);
;
reader.readAsDataURL(blob);
)
);
【讨论】:
以上是关于直接从 JavaScript 打印 PDF的主要内容,如果未能解决你的问题,请参考以下文章
从 MySQL 获取查询并将其打印到 javascript 日历中
如何使用 jquery\javascript 从 firefox 浏览器打印 PDF 文档?