简体   繁体   English

使用 Javascript、HTML5、AngularJS 从浏览器打印嵌入的 PDF

[英]Print embedded PDF from browser with Javascript, HTML5, AngularJS

I'm loading a Base64 encoded PDF as a String into my JavaScript from my server.我正在将 Base64 编码的 PDF 作为字符串从我的服务器加载到我的 JavaScript 中。 My client application is using AngularJS, HTML5.我的客户端应用程序使用的是 AngularJS、HTML5。

My HTML looks like this:我的 HTML 如下所示:

<div id="printablePdfContainer">
  <iframe id="printablePdf" width="100%" height="100%"></iframe>
</div>

My JavaScript looks like this:我的 JavaScript 看起来像这样:

var pdfName = 'data:application/pdf;base64,' + data[0].PrintImage;
var embeddedPdf = document.getElementById('printablePdf');
embeddedPdf.setAttribute('src', pdfName);
$scope.printDocument(embeddedPdf);

My printDocument function looks like this:我的printDocument函数如下所示:

$scope.printDocument = function() {
      var test = document.getElementById('printablePdf');
      if (typeof document.getElementById('printablePdf').print === 'undefined') {

        setTimeout(function(){$scope.printDocument();}, 1000);

      } else {

        var x = document.getElementById('printablePdf');
        x.print();
      }
    };

The printDocument function has been taken from a pre-existing question in stack overflow ( Silent print an embedded PDF ) which gives this as an answer to print an embedded PDF. printDocument函数取自堆栈溢出( Silent print an Embedded PDF )中的一个预先存在的问题,该问题将其作为打印嵌入 PDF 的答案。 However, this doesn't seem to work anymore.但是,这似乎不再起作用。 I'm always getting 'undefined' for the我总是得到“未定义”的

typeof document.getElementById('printablePdf').print === 'undefined'

check.查看。 Seems like .print doesn't exist or something.似乎.print不存在或什么的。

So, my question is this: How can I print an embedded PDF in HTML5, using JavaScript, and without opening a popup window?所以,我的问题是:如何使用 JavaScript 在 HTML5 中打印嵌入的 PDF,并且不打开弹出窗口?

Also answered here: Print Pdf from javascript embed tag也在这里回答: Print Pdf from javascript embed tag

I'm going to post what I learned here after a lot of research for anyone in the future who might find this.经过大量研究后,我将在这里发布我所学到的知识,供将来可能会发现此内容的任何人使用。

PDF's are displayed differently based on browser, browser version, browser configuration, and Operating System. PDF 的显示方式因浏览器、浏览器版本、浏览器配置和操作系统而异。 There are a lot of variables so I'll talk about the most common situations here.有很多变量,所以我将在这里讨论最常见的情况。

  • On all browsers I was unable to call any sort of print() method through Javascript, I was only able to use PdfActions.在所有浏览器上,我无法通过 Javascript 调用任何类型的 print() 方法,我只能使用 PdfActions。 The OPENACTION would call print. OPENACTION 将调用打印。 I embedded these into the PDF using iText.我使用 iText 将这些嵌入到 PDF 中。

  • Chrome uses Adobe's viewer, which doesn't give access to any sort of print() method but does execute PdfActions embedded in the PDF. Chrome 使用 Adob​​e 的查看器,它不能访问任何类型的 print() 方法,但会执行嵌入在 PDF 中的 PdfActions。 So you can embed an 'OpenAction' in a PDF and have the PDF call print whenever it's opened from any application that looks at those actions.因此,您可以在 PDF 中嵌入“OpenAction”,并在从查看这些操作的任何应用程序打开时打印 PDF 调用。

  • Firefox (above a certain version, all recent versions though) uses the Adobe viewer in Windows, which also recognizes PdfActions. Firefox(特定版本以上,但所有最新版本)使用 Windows 中的 Adob​​e 查看器,它也识别 PdfActions。 However, in OSX it loses support for the Adobe viewer and switches to the baked in Firefox viewer (pdf.js).但是,在 OSX 中,它失去了对 Adob​​e 查看器的支持并切换到了 Firefox 查看器 (pdf.js)。 Which does not support PdfActions.哪个不支持 PdfActions。

  • IE: I didn't really test much on IE. IE:我并没有在 IE 上进行太多测试。 Mostly because I gave up on printing PDF's from Javascript after Firefox didn't work on OSX (a req. for me).主要是因为在 Firefox 不能在 OSX 上工作后,我放弃了从 Javascript 打印 PDF(对我来说是一个要求)。

My PDF's were being generated by a server that I control so I ended up making service changes in my server and adding a get PNG service that generated a PNG based on the same markup that the PDF generation uses.我的 PDF 是由我控制的服务器生成的,所以我最终在我的服务器中进行了服务更改,并添加了一个 get PNG 服务,该服务根据 PDF 生成使用的相同标记生成了一个 PNG。 Browsers handle images much better than PDFs, which I knew going in, but hoped that I would just be able to re-use the PDF generation service since it's used elsewhere in my code.浏览器比 PDF 处理图像要好得多,我知道 PDF 是这样处理的,但希望我能够重新使用 PDF 生成服务,因为它在我的代码中的其他地方使用过。

It doesn't answer the question, but it's all the information I have.它没有回答问题,但这是我拥有的所有信息。 My suggestion to anyone who might find this in the future: ditch PDF if possible in this case and go simpler.我对将来可能会发现此问题的任何人的建议:在这种情况下,如果可能,请放弃 PDF 并变得更简单。 Otherwise, please update this question if you know how to call print() through Javascript in FF preview pdf viewer in OSX.否则,如果您知道如何在 OSX 的 FF 预览 pdf 查看器中通过 Javascript 调用 print(),请更新此问题。

-Phil -菲尔

To print a base64 pdf you need to get around the fact that data URIs have no origin and are therefore blocked by modern browers.要打印 base64 pdf,您需要避开数据 URI 没有来源并因此被现代浏览器阻止的事实。

See the note on the date URLs page on MDN: Data URLs .请参阅 MDN 上日期 URL 页面上的注释: 数据 URL

In order to get around this have to either reference the same pdf directly, which is a no-no in this case, or convert the pdf to an object/ blob url.为了解决这个问题,必须直接引用相同的 pdf,在这种情况下这是禁忌,或者将 pdf 转换为对象/blob url。

See MDNs notes on creating an object/blob URL请参阅有关创建对象/blob URL 的MDN 注释

 function b64toBlob(b64Data, contentType) { var byteCharacters = atob(b64Data) var byteArrays = [] for (let offset = 0; offset < byteCharacters.length; offset += 512) { var slice = byteCharacters.slice(offset, offset + 512), byteNumbers = new Array(slice.length) for (let i = 0; i < slice.length; i++) { byteNumbers[i] = slice.charCodeAt(i) } var byteArray = new Uint8Array(byteNumbers) byteArrays.push(byteArray) } var blob = new Blob(byteArrays, { type: contentType }) return blob } var pdfObjectUrl = URL.createObjectURL(b64toBlob(data[0].PrintImage, 'application/pdf')) var embeddedPdf = document.getElementById('printablePdf') embeddedPdf.setAttribute('src', pdfObjectUrl) // Then to print embeddedPdf.contentWindow.print()

Once the data is inside an object URL the contentWindow will not be blocked by the browsers security.一旦数据位于对象 URL 内,浏览器安全性将不会阻止 contentWindow。 The print method will exist on the contentWindow of the iframe.打印方法将存在于 iframe 的 contentWindow 中。

I'm loading a Base64 encoded PDF as a String into my JavaScript from my server.我正在将Base64编码的PDF作为字符串从服务器加载到我的JavaScript中。 My client application is using AngularJS, HTML5.我的客户端应用程序正在使用AngularJS,HTML5。

My HTML looks like this:我的HTML看起来像这样:

<div id="printablePdfContainer">
  <iframe id="printablePdf" width="100%" height="100%"></iframe>
</div>

My JavaScript looks like this:我的JavaScript看起来像这样:

var pdfName = 'data:application/pdf;base64,' + data[0].PrintImage;
var embeddedPdf = document.getElementById('printablePdf');
embeddedPdf.setAttribute('src', pdfName);
$scope.printDocument(embeddedPdf);

My printDocument function looks like this:我的printDocument函数看起来像这样:

$scope.printDocument = function() {
      var test = document.getElementById('printablePdf');
      if (typeof document.getElementById('printablePdf').print === 'undefined') {

        setTimeout(function(){$scope.printDocument();}, 1000);

      } else {

        var x = document.getElementById('printablePdf');
        x.print();
      }
    };

The printDocument function has been taken from a pre-existing question in stack overflow ( Silent print an embedded PDF ) which gives this as an answer to print an embedded PDF. printDocument函数取自堆栈溢出中的一个预先存在的问题( 静默打印嵌入式PDF ),该问题可以作为打印嵌入式PDF的答案。 However, this doesn't seem to work anymore.但是,这似乎不再起作用。 I'm always getting 'undefined' for the我总是对“不确定”

typeof document.getElementById('printablePdf').print === 'undefined'

check.查看。 Seems like .print doesn't exist or something.似乎.print不存在。

So, my question is this: How can I print an embedded PDF in HTML5, using JavaScript, and without opening a popup window?因此,我的问题是:如何在不打开弹出窗口的情况下使用JavaScript在HTML5中打印嵌入式PDF?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM