直接从 JavaScript 打印 PDF

我正在构建一个 HTML 中的 PDF 列表。在列表中,我想包括一个下载链接和一个打印按钮/链接。有没有什么方法可以直接打开 PDF 的打印对话框,而不用让用户看到 PDF 或打开 PDF 查看器?

下载 PDF 到一个隐藏的 iframe 并触发它用 JavaScript 打印?

386553 次浏览

https://github.com/mozilla/pdf.js/

for a live demo http://mozilla.github.io/pdf.js/

it's probably what you want, but I can't see the point of this since modern browsers include such functionality, also it will run terribly slow on low-powered devices like mobile devices that, by the way, have their own optimized plugins and apps.

Based on comments below, it no longer works in modern browsers
This question demonstrates an approach that might be helpful to you: Silent print an embedded PDF

It uses the <embed> tag to embed the PDF in the document:

<embed
type="application/pdf"
src="path_to_pdf_document.pdf"
id="pdfDocument"
width="100%"
height="100%" />

Then you call the .print() method on the element in Javascript when the PDF is loaded:

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();
}
}

You could place the embed in a hidden iframe and print it from there, giving you a seamless experience.

Here is a function to print a PDF from an iframe.

You just need to pass the URL of the PDF to the function. It will create an iframe and trigger print once the PDF is load.

Note that the function doesn't destroy the iframe. Instead, it reuses it each time the function is call. It's hard to destroy the iframe because it is needed until the printing is done, and the print method doesn't has callback support (as far as I know).

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;
}

You can use Print.js (npm install print-js). It's 128kB unpacked and you can find the docs at http://printjs.crabbly.com/.

It doesn't print on IE though, in those cases you'll have to download the PDF instead.

$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")
});

Cross browser solution for printing pdf from base64 string:

  • Chrome: print window is opened
  • FF: new tab with pdf is opened
  • IE11: open/save prompt is opened

.

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))

BONUS - Opening blob file in new tab for IE11

If you're able to do some preprocessing of the base64 string on the server you could expose it under some url and use the link in printJS :)

I used this function to download pdf stream from server.

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)
}

You can download the pdf file using fetch, and print it with 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);
})
});

Simplification of @Nicolas BADIA's answer:

function printPDF (url)
{
let pdfFrame = document.body.appendChild(document.createElement('iframe'));
pdfFrame.style.display = 'none';
pdfFrame.onload = () => (void pdfFrame.contentWindow.print());
pdfFrame.src = url;
}

I resolve problem -_- hehe

function PrintPdf (pdf) {
var iframe = document.createElement('iframe');
iframe.style.display = "none";
iframe.src = pdf;
document.body.appendChild(iframe);
iframe.contentWindow.focus();
iframe.contentWindow.print();
}