繁体   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