【问题标题】:Print PDF in Firefox在 Firefox 中打印 PDF
【发布时间】:2016-01-20 04:14:31
【问题描述】:

如何在 Firefox 中打印 PDF?

此功能在 Chrome 中有效,但在 Firefox 中无效

function print_pdf(url){
    var id = 'iframe', html = '<iframe id="'+id+'" src="'+url+'" style="display:none"></iframe>';
    $('#main').append(html);
    $('#'+id).load(function(){
        document.getElementById(id).contentWindow.print();
    }
}

错误

Error: Permission denied to access property "print"

【问题讨论】:

  • 它不能正常工作还是显示一些错误?可以提供一个jsfiddle给我们看看吗?
  • 打印出来的页面是空的。。就像一个空的网页,页眉是URL,页脚是日期
  • TypeError: document.frames 未定义
  • 我刚刚注意到,你有style="display:none"。如果项目未显示,则不会打印。把打印的页面想象成一个屏幕。如果没有显示项目,则不会打印。
  • DOM 变量/对象未定义。

标签: javascript jquery firefox printing pdf-generation


【解决方案1】:

Firefox:访问属性“打印”的权限被拒绝

这是bug in firefox。在本地可以通过转到about:config 并将pdfjs.disabled 的属性设置为true 来禁用它。唯一可能的解决方法是使用服务器端脚本并修改 pdf。使用php你可以使用fpdf并嵌入extensions来实现js(包括print()函数)或简单地将pdf转换为图像,返回url并打印。您可以使用FPDI 来修改现有的 pdf。我会给你一个例子,说明我是如何让它与 PHP 一起工作的。

使用FPDIPDF_JS 生成带有内联javascript(自动打印)的PDF 文件

require_once('fpdf.php');
require_once('fpdi.php');

class PDF_JavaScript extends FPDI {

    var $javascript;
    var $n_js;

    function IncludeJS($script) {
        $this->javascript=$script;
    }

    function _putjavascript() {
        $this->_newobj();
        $this->n_js=$this->n;
        $this->_out('<<');
        $this->_out('/Names [(EmbeddedJS) '.($this->n+1).' 0 R]');
        $this->_out('>>');
        $this->_out('endobj');
        $this->_newobj();
        $this->_out('<<');
        $this->_out('/S /JavaScript');
        $this->_out('/JS '.$this->_textstring($this->javascript));
        $this->_out('>>');
        $this->_out('endobj');
    }

    function _putresources() {
        parent::_putresources();
        if (!empty($this->javascript)) {
            $this->_putjavascript();
        }
    }

    function _putcatalog() {
        parent::_putcatalog();
        if (!empty($this->javascript)) {
            $this->_out('/Names <</JavaScript '.($this->n_js).' 0 R>>');
        }
    }
}

class PDF_AutoPrint extends PDF_JavaScript
{
    function AutoPrint($dialog=false)
    {
        //Open the print dialog or start printing immediately on the standard printer
        $param=($dialog ? 'true' : 'false');
        $script="print($param);";
        $this->IncludeJS($script);
    }

    function AutoPrintToPrinter($server, $printer, $dialog=false)
    {
        $script = "document.contentWindow.print();";
        $this->IncludeJS($script);
    }
}

$pdf=new PDF_AutoPrint();
$pdf->setSourceFile("mozilla.pdf");
//Open the print dialog
$tplIdx = $pdf->importPage(1, '/MediaBox');
$pdf->addPage();
$pdf->useTemplate($tplIdx, 10, 10, 90);
$pdf->AutoPrint(true);
$pdf->Output('generated.pdf', 'F');

现在您可以简单地将生成的 pdf 附加到您的页面,并且包含的​​ javascript 将调用 print() 函数。您甚至不必再手动调用它。但是,在 Firefox 中,这仅适用于 visibility: hidden 而不适用于 display: none

function print_pdf(url){
    var iFrameJQueryObject = $('<iframe id="iframe" src="'+url+'" style="visibility: hidden"></iframe>');
    $('#foo').append(iFrameJQueryObject);
}
print_pdf('mozilla_generated.pdf');

Chrome:安全错误(跨域)

pdf 应位于同一主机上。在我的测试中,Firefox 对其他域没问题,但 chrome 给了我跨域错误。


Firefox:打印页面仅包括 about:blank

您将在 Firefox (jsfiddle) 中获得一个空白页面,因为它会在加载任何内容之前打印 iframe。 $(document).onload() 等提到的方法没有帮助,因为它们只等待 DOM 加载,而 setTimeout() 仍然会导致错误,因为您不知道 iFrame 需要多长时间才能加载。

您可以使用 jQuery 的 load() 简单地解决此问题。 (doc) 这将使您可以使用回调函数作为参数。

如果提供了“完成”回调,它会在后处理和 HTML 插入完成后执行。 jQuery 集合中的每个元素都会触发一次回调,并依次为每个 DOM 元素设置this

代码示例 1

function print_pdf(url){
    var id = 'iframe', html = '<iframe id="'+id+'" src="'+url+'" style="display:none"></iframe>';
    $('body').append(html);
    // wait for the iFrame to fully load and call the print() function afterwards
    $('#' + id).load(function () {
        document.getElementById(id).contentWindow.print();
    });
}

您也可以直接创建一个 jQuery 对象并使用 jQuery 的 on() (doc) 附加任何事件处理程序。

代码示例 2 (jsfiddle)

function print_pdf(url){
    var iFrameJQueryObject = $('<iframe id="iframe" src="'+url+'" style="display:none"></iframe>');
    $('body').append(iFrameJQueryObject);
    iFrameJQueryObject.on('load', function(){
        $(this).get(0).contentWindow.print();
    });
}

【讨论】:

  • 您最好将 iframe 创建为 JS 对象而不是字符串。这样,您可以在将其添加到页面之前为其添加事件处理程序,例如 onload。
  • jsfiddle 在使用 iframe 的时候会出现 x-origin 的问题,所以很不方便。我仍然可以使用与 url 相同的 url。
  • 我在 Firefox 中收到此错误:Error: Permission denied to access property "print"
  • 如果你把一个实际的 PDF 文件放到函数中它不起作用jsfiddle.net/zrp6sd6h/4Error: Permission denied to access property "print"
  • - 我认为这与 Firefox 使用自己的 javascript PDF 查看器有关 pdf.js
【解决方案2】:

编辑、更新

尝试使用window.onload 事件,document.createElement()onload 事件,setTimeout()duration 设置为2000,在将元素附加到document 后设置srcsrc

window.onload = function() {
    function print_pdf(url){
        var id = "iframe", frame = document.createElement("iframe");
        frame.setAttribute("id", id);
        frame.setAttribute("width", "800px");
        frame.setAttribute("height", "600px");
        frame.setAttribute("allowfullscreen", "true");
        frame.setAttribute("name", "printframe");
        document.body.appendChild(frame);
        frame.onload = function() {
          this.requestFullScreen = this.mozRequestFullScreen 
                                   || this.webkitRequestFullScreen;
          this.requestFullScreen();
          setTimeout(function() {
            print()
          },2000)
        }
        frame.setAttribute("src", url);
    }
    print_pdf("http://zeitreisen.zeit.de/wp-content/uploads/2014/09/pdftest2.pdf");
}

plnkrhttp://plnkr.co/edit/mHBNmc5mdM0YJRwRbYif?p=preview

【讨论】:

  • 代码在打印对话框出现之前触发alert:pdf.js 未完全加载
  • @clarkk “代码在打印对话框出现之前触发警报” 调整个别 Firefox 浏览器打印首选项以在打印时执行默认操作? “并且 PDF 必须被隐藏” 不确定“PDF 必须被隐藏”?使用display:none 加载iframe 将iframe 调整为display:block,然后再调用.print()?如果iframe 已加载并且.print() 立即调用打印窗口应显示iframe 内容并在父window 在打印对话框取消或记录打印到文件系统时重新获得焦点之前立即获得焦点。
  • @clarkk 可以使用服务器端解决方案来满足要求吗?
  • 我更喜欢 javascript 解决方案。但告诉我你的想法
  • @clarkk 查看更新后的帖子,添加了window.onload 事件,添加了2000durationsetTimeout。每晚尝试,铬;似乎每次都返回相同的结果。
【解决方案3】:

PDF 支持 Javascript。在创建 PHP 生成的 PDF 时,我需要具有自动打印功能,并且我能够使用 FPDF 让它工作:

http://www.fpdf.org/en/script/script36.php

【讨论】:

    【解决方案4】:

    @clarkk 我建议使用功能更强大的东西,很多人都已经介绍过我的建议是使用http://pdfmake.org/#/

    我在我的数据表中使用了这个 pdfmake,它绝对完美。请记住,如果您从表格中打印超过 10 000 行,或者它会耗尽浏览器的内存:)

    【讨论】:

    • 在客户端创建 PDF 不是一种选择。然后您必须同时维护服务器端 PDF 生成器和客户端 PDF 生成器。客户端 PDF 生成器是主要的
    • 是的,你是对的,但在很少的信息中我可以告诉你它超级快。它还在 html5 上中继,当你想要一个跨浏览器的兼容性很好时,它也是一个免费库,你不支持任何东西,一切都是由你只需要替换库的人完成的,所以它不是很大的支持.
    【解决方案5】:

    我已经有一段时间没有使用它了,但这是我用来从 iframe 打印 pdf 的方法...

    function printfile() {
        window.frames['objAdobePrint'].focus();
        window.frames['objAdobePrint'].print();
    }
    
    <iframe src="urlOfPdf" name="objAdobePrint" id="objAdobePrint"></iframe>
    <button onclick="printfile();">Print</button>
    

    【讨论】:

      【解决方案6】:

      您可以在不创建新iframe(仅使用css)的情况下实现打印功能以防止安全问题:

      var style = document.createElement("style");
      style.setAttribute("media", "print"); //style.setAttribute("media", "screen,print");
      style.appendChild(document.createTextNode(""));
      document.head.appendChild(style);
      var width = $("#printDiv").width();
      var height = $("#printDiv").height();
      style.sheet.insertRule("body { width: 210mm !important, height: 25.4mm !important; visibility: hidden; }", 0);
      style.sheet.insertRule("#printDiv { visibility: visible; position: fixed !important;top: 5px;  left: 5px; width:" + width + "px;height:" + height + ";  page-break-after: avoid;}", 0);
      
      window.focus();
      window.print(true);
      style.remove();
      

      【讨论】:

        【解决方案7】:

        Print a pdf with javascript or jquery

        在 html 中创建 iframe:

        <iframe id="pdf-iframe">
        

        然后更改该 iframe 的 src 并在加载时打印它:

        $('#pdf-iframe').attr("src", pdf_url).load(function(){
            document.getElementById('pdf-iframe').contentWindow.print();
        });
        

        或者,您可能想试试https://mozilla.github.io/pdf.js/

        【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-02-07
        • 2014-10-19
        • 2013-05-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多