簡體   English   中英

無需打開即可打印 pdf

[英]Print a pdf without visually opening it

我想要構建的是,通過單擊一個按鈕,我想觸發 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 年,我覺得跨瀏覽器實現這仍然很痛苦。

更新:此鏈接詳細介紹了一個優雅的解決方案,該解決方案涉及編輯第一頁的頁面屬性並在頁面打開時添加操作。 適用於所有瀏覽器(因為瀏覽器將執行放置在操作部分的 JavaScript)。 需要 Adob​​e Acrobat Pro。


2016 年似乎沒有為打印問題帶來新的進展。 有一個類似的問題,為了使打印跨瀏覽器,我使用PDF.JS解決了它,但不得不對源代碼進行單行添加(他們要求您以任何方式構建它)。

想法:

  • https://mozilla.github.io/pdf.js/getting_started/#download下載預先構建的穩定版本,並將“build”和“web”文件夾添加到項目中。
  • 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 中測試。

在花了過去幾個小時試圖弄清楚這一點並在這里進行了大量搜索之后,我已經確定...

用於打印HTML5 Web API 規范指示printing steps必須在beforeprint ,一個簡單事件(不可取消的事件)中觸發到正在打印的文檔的窗口對象(以及任何嵌套的瀏覽上下文,這與 iframe 相關)以允許在打印之前更改文檔。 此步驟是瀏覽器內部的,您無法調整。 在此過程中,瀏覽器的打印對話框有時會顯示文件的預覽(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使其正常工作,那么在您想要的跨瀏覽器方法中可能效果最佳。

我找到了一些有關此主題的參考資料,它們可能會有所幫助:

我將在此處發布 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();
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM