简体   繁体   English

从javascript触发base64编码PDF的打印预览

[英]Trigger print preview of base64 encoded PDF from javascript

I've looked around stackoverflow trying to find a way to do this for a while now, and can't find a suitable answer.我已经环顾了stackoverflow,试图找到一种方法来做到这一点,但找不到合适的答案。 I need to be able to load a PDF in either a new window or an iframe via a base64 encoded string and trigger a print preview of it immediately after loading it.我需要能够通过 base64 编码字符串在新窗口或 iframe 中加载 PDF,并在加载后立即触发它的打印预览。 I can easily load the PDF using both of those methods, but can't actually get it to show the print preview properly.我可以使用这两种方法轻松加载 PDF,但实际上无法正确显示打印预览。 Here is what I've tried:这是我尝试过的:

  1. Using embed element in a new window.在新窗口中使用embed元素。 Calling window.print() is blank, even after the content is loaded.即使在加载内容之后,调用window.print()也是空白的。
  2. Using a hidden, dynamically created iframe with src="data:application/pdf;base64,JVBERi0..." and calling myFrame.contentWindow.print() .使用带有src="data:application/pdf;base64,JVBERi0..."的隐藏的、动态创建的iframe并调用myFrame.contentWindow.print() But this gives a CORS error.但这会导致 CORS 错误。 I'm not sure why, because I'm not loading a new domain through the iframe, just content.我不知道为什么,因为我没有通过 iframe 加载新域,只是内容。
  3. Open a new window with only an iframe element like the one in #2 and calling a print on the whole window.打开一个只有iframe元素的新窗口,如#2 中的那个,并在整个窗口上调用打印。 This also shows a blank white page.这也显示一个空白的白页。
  4. Open a new window with the data uri and print it.使用数据 uri 打开一个新窗口并打印它。 window.open('data:application/pdf;base64,JVBERi0...').print(); . . This doesn't work either, as it doesn't even show a print preview at all.这也不起作用,因为它甚至根本不显示打印预览。 I've also tried delaying it with a setTimeout but that doesn't do anything either.我也试过用setTimeout延迟它,但这也没有任何作用。

At this point I'm very confused as to why none of these work, especially because in Chrome it display's custom menu bars like this:在这一点上,我很困惑为什么这些都不起作用,特别是因为在 Chrome 中它显示的自定义菜单栏是这样的:

Chrome 打印预览

And if I click the actual print icon there, the print preview is perfect.如果我点击那里的实际打印图标,打印预览是完美的。 Whatever Chrome is doing when I click that button is exactly what I want to accomplish.当我单击该按钮时,Chrome 正在执行的任何操作正是我想要完成的。 Is there anyway to trigger that functionality?反正有没有触发该功能? Or is there another way to accomplish what I want?或者有另一种方法来完成我想要的吗? And just to clarify, I only need this to work in Chrome, I don't need to worry about other browsers.澄清一下,我只需要它在 Chrome 中工作,我不需要担心其他浏览器。

Here is a solution for point #3:这是第 3 点的解决方案:

Open a new window with only an iframe element like the one in #2 and calling a print on the whole window.打开一个只有 iframe 元素的新窗口,如#2 中的那个,并在整个窗口上调用打印。 This also shows a blank white page.这也显示一个空白的白页。

In your case, it's throwing CORS error because it looks like for iframe src you are giving the base64String not the URL.在您的情况下,它会抛出 CORS 错误,因为对于 iframe src,您似乎提供的是 base64String 而不是 URL。 Here is what you can do这是你可以做的

  1. Take your base64String, convert it to a Blob将 base64String 转换为 Blob
  2. Generate a URL from the Blob从 Blob 生成 URL
  3. Provide the generated URL to iframe.将生成的 URL 提供给 iframe。
  4. After this you can print the content using iframe.contentWindow.print() ;在此之后,您可以使用iframe.contentWindow.print()打印内容;

Here is the code to convert base64 to Blob这是将base64转换为Blob的代码

'use strict';

const b64toBlob = (b64Data, contentType = '', sliceSize = 512) => {
    const byteCharacters = atob(b64Data);
    const byteArrays = [];

    for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
        const slice = byteCharacters.slice(offset, offset + sliceSize),
            byteNumbers = new Array(slice.length);
        for (let i = 0; i < slice.length; i++) {
            byteNumbers[i] = slice.charCodeAt(i);
        }
        const byteArray = new Uint8Array(byteNumbers);

        byteArrays.push(byteArray);
    }

    const blob = new Blob(byteArrays, { type: contentType });
    return blob;
}


const contentType = "application/pdf",
    b64Data = "YourBase64PdfString", //Replace this with your base64String
    blob = this.b64toBlob(b64Data, contentType),
    blobUrl = URL.createObjectURL(blob);

Use blobUrl to the src of Iframe, once it's done, you can call print() on iframe as shown below使用blobUrl到 iframe 的src ,完成后,您可以在 iframe 上调用print() ,如下所示

const iframeEle = document.getElementById("Iframe");
if (iframeEle) {
    iframeEle.contentWindow.print();
}

Hope this helps...希望这有助于...

More details on base64 to Blob is here Creating a Blob from a base64 string in JavaScript有关 base64 到 Blob 的更多详细信息,请参见在 JavaScript 中从 base64 字符串创建 Blob

you can use this,你可以用这个

function "printPreview(binaryPDFData)" to get print preview dialog of binary pdf data.函数“printPreview(binaryPDFData)”获取二进制pdf数据的打印预览对话框。

printPreview = (data, type = 'application/pdf') => {
    let blob = null;
    blob = this.b64toBlob(data, type);
    const blobURL = URL.createObjectURL(blob);
    const theWindow = window.open(blobURL);
    const theDoc = theWindow.document;
    const theScript = document.createElement('script');
    function injectThis() {
        window.print();
    }
    theScript.innerHTML = `window.onload = ${injectThis.toString()};`;
    theDoc.body.appendChild(theScript);
};

b64toBlob = (content, contentType) => {
    contentType = contentType || '';
    const sliceSize = 512;
     // method which converts base64 to binary
    const byteCharacters = window.atob(content); 

    const byteArrays = [];
    for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
        const slice = byteCharacters.slice(offset, offset + sliceSize);
        const byteNumbers = new Array(slice.length);
        for (let i = 0; i < slice.length; i++) {
            byteNumbers[i] = slice.charCodeAt(i);
        }
        const byteArray = new Uint8Array(byteNumbers);
        byteArrays.push(byteArray);
    }
    const blob = new Blob(byteArrays, {
        type: contentType
    }); // statement which creates the blob
    return blob;
};

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

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