我想要构建的是通过单击按钮我想触发PDF文件的打印,但不打开它。
+-----------+
| Print PDF |
+-----------+
^ Click *---------> printPdf(pdfUrl)
我第一次尝试它的方法是使用iframe:
var $iframe = null;
// This is supposed to fix the onload bug on IE, but it's not fired
window.printIframeOnLoad = function() {
if (!$iframe.attr("src")) { return; }
var PDF = $iframe.get(0);
PDF.focus();
try {
// This doesn't work on IE anyways
PDF.contentWindow.print();
// I think on IE we can do something like this:
// PDF.document.execCommand("print", false, null);
} catch (e) {
// If we can't print it, we just open it in the current window
window.location = url;
}
};
function printPdf(url) {
if ($iframe) {
$iframe.remove();
}
$iframe = $('<iframe>', {
class: "hide",
id: "idPdf",
// Supposed to be a fix for IE
onload: "window.printIframeOnLoad()",
src: url
});
$("body").prepend($iframe);
}
这适用于Safari(桌面和iOS)和Chrome(我们可以将其概括为webkit吗?)。
在Firefox上,PDF.contentWindow.print()
以permission denied
错误结束(即使pdf是从同一个域加载的)。
在IE(11)上,onload
处理程序无效。
现在,我的问题是:是否还有另一种更好的方法来打印pdf而无需在视觉上将其打开给用户?
跨浏览器的事情在这里至关重要。我们应该尽可能多地支持浏览器。
实现这一目标的最佳方法是什么?我的开始是好的吗?如何完成它?
我们现在在2016年,我觉得在整个浏览器中实施这仍然很难。
答案 0 :(得分:15)
更新:此link详细介绍了一个优雅的解决方案,其中包括编辑第一页的页面属性并在页面打开时添加操作。适用于所有浏览器(因为浏览器将执行放置在actions部分中的JavaScript)。需要Adobe Acrobat Pro。
2016年似乎没有给打印问题带来新的进步。有一个类似的问题,并使打印跨浏览器我使用PDF.JS解决它,但不得不对源进行单线程添加(他们要求你在任何方面建立它)。
这个想法:
viewer.html
文件是具有丰富界面并包含打印功能的PDF。我在该文件中添加了一个链接到我自己的JavaScript,它只是在延迟后触发window.print()。添加到查看器的链接:
<script src="viewer.js"></script>
<!-- this autoPrint.js was added below viewer.js -->
<script src="autoPrint.js"></script>
</head>
autoPrint.js
javascript:
(function () {
function printWhenReady() {
if (PDFViewerApplication.initialized) {
window.print();
}
else {
window.setTimeout(printWhenReady, 3000);
}
};
printWhenReady();
})();
然后我可以在iframe的src中调用viewer.html?file=
并隐藏它。由于Firefox,不得不使用可见性而不是显示样式:
<iframe src="web/viewer.html?file=abcde.pdf" style="visibility: hidden">
结果:在短暂延迟后显示打印对话框,其中PDF对用户隐藏。
在Chrome,IE,Firefox中测试。
答案 1 :(得分:6)
花了几个小时试图弄清楚这个,我在这里搜索了很多......
HTML5 Web API spec for Printing表示其中一个printing steps
必须向正在打印的文档的窗口对象触发beforeprint,一个简单事件(不可取消的事件)以及任何嵌套的浏览上下文,这与iframe相关,以允许在打印之前更改Document。此步骤是浏览器的内部步骤,而不是您可以调整的内容。在此过程中,浏览器的打印对话框有时会显示文件的预览(Chrome会执行此操作)...因此,如果您的目标是永远不会将文件显示给查看者,则可能会被卡住。
最接近实现这一目标的方法是创建一个index.html
文件,其中包含一个按钮,其中包含提供上下文的data- *属性。将data-print-resource-uri
属性中的path / filename.ext更改为您自己的本地文件。
<!DOCTYPE html>
<html>
<head>
<title>Express</title>
<link rel="stylesheet" href="/stylesheets/style.css">
</head>
<body>
<h1>Express</h1>
<p>Welcome to Express</p>
<button name="printFile" id="printFile" data-print-resource-uri="/binary/paycheckStub.pdf" data-print-resource-type="application/pdf">Print File</button>
<iframe name="printf" id="printf" frameborder="0"></iframe>
<script src="/javascripts/print.js"></script>
</body>
</html>
然后在print.js
文件中,我尝试了一些东西,但从来没有完全正常工作(留下我在评论中玩过的不同内容)。
// Reference vars
var printButton = document.getElementById('printFile');
var printFrame = document.getElementById('printf');
// onClick handler
printButton.onclick = function(evt) {
console.log('evt: ', evt);
printBlob('printf', printButton.getAttribute('data-print-resource-uri'), printButton.getAttribute('data-print-resource-type'));
}
// Fetch the file from the server
function getFile( fileUri, fileType, callback ) {
var xhr = new XMLHttpRequest();
xhr.open('GET', fileUri);
xhr.responseType = 'blob';
xhr.onload = function(e) {
// Success
if( 200 === this.status ) {
// Store as a Blob
var blob = new Blob([this.response], {type: fileType});
// Hang a URL to it
blob = URL.createObjectURL(blob);
callback(blob);
} else {
console.log('Error Status: ', this.status);
}
};
xhr.send();
}
function printBlob(printFrame, fileUri, fileType) {
// Debugging
console.log('inside of printBlob');
console.log('file URI: ', fileUri);
console.log('file TYPE: ', fileType);
// Get the file
getFile( fileUri, fileType, function(data) {
loadAndPrint(printFrame, data, fileType);
});
}
function loadAndPrint(printFrame, file, type) {
// Debugging
console.log('printFrame: ', printFrame);
console.log('file: ', file);
window.frames[printFrame].src = file;
window.frames[printFrame].print();
/*
// Setup the print window content
var windowContent = '<!DOCTYPE html>';
windowContent += '<html>'
windowContent += '<head><title>Print canvas</title></head>';
windowContent += '<body>'
windowContent += '<embed src="' + file + '" type="' + type + '">';
windowContent += '</body>';
windowContent += '</html>';
// Setup the print window
var printWin = window.open('','','width=340,height=260');
printWin.document.open();
printWin.document.write(windowContent);
printWin.document.close();
printWin.focus();
printWin.print();
printWin.close();
*/
}
我认为,如果您能够使用Blob
使其正常工作,则可能会在您想要的跨浏览器方法中发挥最佳效果。
我找到了一些关于这个主题的参考资料,可能会有所帮助:
答案 2 :(得分:0)
我将在这里发布 IE 11 上 OP 函数的修改功能
printPdf: function (url) {
$('#mainLoading').show();
let iframe = $('#idPdf');
if (iframe) {
iframe.remove();
}
iframe = $('<iframe>', {
style: "display:none",
id: "idPdf"
});
$("body").prepend(iframe);
$('#idPdf').on("load", function(){
utilities.printIframeOnLoad()
})
utilities.getAsyncBuffer(url, function(response){
let path = utilities.getPdfLocalPath(response);
$('#idPdf').attr('src', path);
})
},
printIframeOnLoad: function () {
let iframe = $('#idPdf');
if (!iframe.attr("src")) { return; }
var pdf = iframe.get(0);
pdf.focus();
$('#mainLoading').hide();
pdf.contentWindow.print();
},
getPdfLocalPath: function (data) {
var filename = "Application_" + utilities.uuidv4() + ".pdf";
var blob = new Blob([data], { type: 'application/pdf' });
if (window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveBlob(blob, filename);
return filename;
}
else {
let url = window.URL || window.webkitURL;
let href = url.createObjectURL(blob);
return href;
}
},
getAsyncBuffer: function (uriPath, callback) {
var req = new XMLHttpRequest();
req.open("GET", uriPath, true);
req.responseType = "blob";
req.onreadystatechange = function () {
if (req.readyState === 4 && req.status === 200) {
callback(req.response);
}
};
req.send();
}