2016-07-28 270 views
24

我想要构建的东西是通过单击按钮我想触发PDF文件的打印,但不打开它。打印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

所以,如果我理解正确,你不想显示PDF,但仍然打印它...所以只需用其他词下载?或者按照正常方式进行操作并隐藏该部分。 – Jorrex

+0

打开PDF时,不能将PDF设置为自动打印? – epascarello

+0

@Jorrex不,在隐藏的iframe中打开它,并在该iframe的上下文中打开打印对话框。 iframe不是要求,但这是我的第一次尝试。我不确定是否有其他方法可以做到这一点......简而言之:当我点击按钮时,打印对话框应该打开并打印该pdf。 –

回答

9

UPDATE:这link详细介绍了涉及编辑页面属性为第一页和添加的页面打开一个动作一个完美的解决方案。适用于所有浏览器(因为浏览器将执行位于操作部分的JavaScript)。需要Adobe Acrobat Pro。


看来2016对印刷问题没有任何新的进展。有一个类似的问题,并使打印跨浏览器我解决了它使用PDF.JS,但不得不作出一个单一的补充来源(他们要求你建立在任何方面)。

的想法:

  • https://mozilla.github.io/pdf.js/getting_started/#download下载预构建的稳定版,并添加了“构建”和“网络”文件夹到项目中。
  • 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(); 
})(); 
  • 然后我可以把呼叫viewer.html?file=中的iframe src和隐藏。不得不使用可视性,不显示因为火狐的样式:

    <iframe src="web/viewer.html?file=abcde.pdf" style="visibility: hidden"> 
    

结果:打印对话框与PDF在短暂的延迟从用户被隐藏后显示。

经过Chrome,IE,Firefox的测试。

+0

Pdf.js绝对是一件事情。现代浏览器,令人讨厌的部分是它有印刷错误(像素化输出,错误字体等),我也尝试过这种做法 –

+0

没错,为了让事情继续下去,我承认并尽可能在Pdf.js中解决了缺陷。这些年来,pdf打印将变得简单... – Balah

+0

您可以在您的答案中添加[此解决方案](http://nvision.co/blog/tips-and-tricks/auto-print-pdf-file-打开/)工作?浏览器执行js放在那里,所以通过在pdf中添加'window.print()'解决了这个问题。 –

5

花费过去几个小时试图找出这一个和很多在这里搜索后是我决定...

HTML5 Web API spec for Printing表明printing steps中的一个必须火beforeprint,一个简单的事件(一个不可取消的事件),打印到正在打印的文档的窗口对象(以及任何嵌套的浏览上下文,这涉及到iframe),以便在打印之前更改文档。这一步是浏览器内部的,而不是你可以调整的。在这个过程中,浏览器的打印对话框有时会显示文件的预览(Chrome会这样做)...所以如果您的目标是永远不会向查看器显示文件,您可能会被卡住。

最接近实现这一目标的是创建了一个index.html文件,该文件具有包含提供上下文的data- *属性的按钮。将data-print-resource-uri属性中的路径/ 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可能工作最好在你想要的跨浏览器的方法。

我发现这个话题,这可能是一些实用的参考文献:

+0

有趣的方法,但我没有看到将src设置为blob url或只设置文件url直到至少,在解决了代码中的小问题之后,我在Firefox中遇到了同样的错误:'拒绝访问属性的权限'print'' –