从 javascript 触发 base64 编码 PDF 的打印预览
Posted
技术标签:
【中文标题】从 javascript 触发 base64 编码 PDF 的打印预览【英文标题】:Trigger print preview of base64 encoded PDF from javascript 【发布时间】:2017-03-21 01:06:49 【问题描述】:我已经环顾 *** 一段时间,试图找到一种方法来做到这一点,但找不到合适的答案。我需要能够通过 base64 编码的字符串在新窗口或 iframe 中加载 PDF,并在加载后立即触发它的打印预览。我可以使用这两种方法轻松加载 PDF,但实际上无法正确显示打印预览。这是我尝试过的:
-
在新窗口中使用
embed
元素。调用 window.print()
是空白的,即使在内容加载之后也是如此。
使用隐藏的、动态创建的iframe
和src="data:application/pdf;base64,JVBERi0..."
并调用myFrame.contentWindow.print()
。但这会产生 CORS 错误。我不知道为什么,因为我没有通过 iframe 加载新域,只是内容。
打开一个新窗口,其中只有一个iframe
元素,如#2 中的元素,并在整个窗口上调用打印。这也显示了一个空白的白页。
使用数据 uri 打开一个新窗口并打印它。 window.open('data:application/pdf;base64,JVBERi0...').print();
。这也不起作用,因为它甚至根本不显示打印预览。我也尝试过使用setTimeout
延迟它,但这也无济于事。
此时我很困惑为什么这些都不起作用,特别是因为在 Chrome 中它显示的自定义菜单栏是这样的:
如果我点击那里的实际打印图标,打印预览是完美的。当我单击该按钮时,无论 Chrome 正在做什么,这正是我想要完成的。反正有触发该功能吗?还是有另一种方法来完成我想要的?澄清一下,我只需要它在 Chrome 中工作,我不需要担心其他浏览器。
【问题讨论】:
你设法让它工作了吗?我尝试了同样的方法似乎没有任何效果 @db306 不,我真的不认为这是可能的,我已经尝试了我能想到的一切。 Chrome 中的 PDF 查看器实际上是一个插件,我认为不可能通过 javascript 与之交互。我认为使用 PDF.js 可能可以实现这一点,但我还没有时间尝试实现它 我实际上设法让它在弹出窗口上打印,但是,该函数会很快被触发,并且鉴于每个浏览器,我无法在 pdf 格式化程序上添加事件侦听器有不同的读者。我可以让它工作的唯一方法是将 pdf 文件保存在服务器上,在隐藏的 iframe 上提供 pdf 并在 iframe 加载后打印。希望这对某人有所帮助。谢谢 这适用于使用 iframe 的 chrome,但我在使用 Safari 时遇到问题,它会在 PDF 呈现之前尝试打印,并且 onload 不起作用 【参考方案1】:这是第 3 点的解决方案:
打开一个新窗口,其中只有一个 iframe 元素,如 #2 中的那个,并在整个窗口上调用打印。这也显示了一个空白的白页。
在您的情况下,它会引发 CORS 错误,因为对于 iframe src,您提供的是 base64String 而不是 URL。这是你可以做的事情
-
获取 base64String,将其转换为 Blob
从 Blob 生成 URL
将生成的 URL 提供给 iframe。
之后,您可以使用
iframe.contentWindow.print()
打印内容;
这是将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);
使用blobUrl
到iframe的src
,完成后就可以在iframe上调用print()
如下图
const iframeEle = document.getElementById("Iframe");
if (iframeEle)
iframeEle.contentWindow.print();
希望这会有所帮助...
更多关于base64到Blob的细节在这里Creating a Blob from a base64 string in JavaScript
【讨论】:
这非常有效。我只需要添加一个 setTimeout(),这样浏览器就有时间渲染 PDF。否则它只会打印一个空白页。 这会为我返回Blocked a frame with origin "http://localhost:3000" from accessing a cross-origin frame.
错误。我有Allow-Origin=*
感谢您为这项工作提供的解决方案,但我不明白 sliceSize 是什么以及什么??【参考方案2】:
你可以用这个,
函数"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;
;
【讨论】:
这在 Chrome 和 Firefox 中完美运行,但在 IE 中却不行。 IE中是否有任何修复。无法将 blob url 添加到 IE 中的窗口。 无论如何要让它在打印后自动关闭?我对图像有类似的工作,我可以使用window.close()
来实现这一点,但是当我将window.close()
放在上面的代码中时,它会在我有机会打印之前关闭窗口,即使设置了很短的 setTimeout。
以上是关于从 javascript 触发 base64 编码 PDF 的打印预览的主要内容,如果未能解决你的问题,请参考以下文章
JSON 编码/解码 JavaScript 中的 base64 编码/解码
将 AWS KMS ECDSA_SHA_256 签名从 DER 编码的 ANS.1 格式转换为 JWT base64url 编码的 R || NodeJS/Javascript 中的 S 格式