web-dev-qa-db-fra.com

Impression PDF dans Firefox

Comment imprimer un PDF dans Firefox?

Cette fonction fonctionne dans Chrome mais pas dans 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();
    }
}

erreur

Error: Permission denied to access property "print"
43
clarkk

Firefox: autorisation d'accès à la propriété "print" refusée

C'est un bug dans firefox . Localement, il peut être désactivé en allant à about:config et en définissant la propriété de pdfjs.disabled sur true. La seule solution possible consiste à utiliser un script côté serveur et à modifier le fichier PDF. En utilisant php, vous pouvez utiliser fpdf et embed extensions pour implémenter js (y compris la fonction print()) ou simplement convertir le pdf en image, renvoyer l’URL et l’imprimer. Vous pouvez utiliser FPDI pour modifier le pdf existant. Je vais vous donner un exemple de la façon dont je l’ai fait fonctionner avec PHP.

Génération d'un fichier PDF avec JavaScript intégré (impression automatique) à l'aide de FPDI et PDF_JS

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');

Maintenant, vous pouvez simplement ajouter le pdf généré à votre page et le javascript inclus appellera la fonction print(). Vous n'avez même plus besoin de l'appeler manuellement. Cependant, dans Firefox, cela ne fonctionnera qu'avec visibility: hidden et non avec 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: erreur de sécurité (origine croisée)

Le pdf devrait être situé sur le même hôte. Firefox convenait à d’autres domaines dans mes tests, mais chrome m’a donné des erreurs croisées.


Firefox: la page imprimée comprend uniquement about:blank

Vous obtiendrez une page vide dans firefox ( jsfiddle ), car elle imprimera l’iframe avant que le contenu n’ait été chargé. Les méthodes mentionnées, telles que $(document).onload(), ne seront d'aucun secours, car elles n'attendent que le DOM à charger et setTimeout() peut toujours générer des erreurs, car vous ne savez pas combien de temps il faut pour charger l'iFrame.

Vous pouvez simplement résoudre ce problème en utilisant la fonction load() de jQuery. ( doc ) Cela vous donnera la possibilité d'utiliser une fonction de rappel en tant que paramètre.

si un rappel "complet" est fourni, il est exécuté après le post-traitement et l'insertion HTML ont été effectués. Le rappel est déclenché une fois pour chaque élément de la collection jQuery et this est défini sur chaque élément DOM à son tour.

Exemple de code 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();
    });
}

Vous pouvez également créer directement un objet jQuery et utiliser la fonction on() ( doc ) de jQuery pour attacher tout gestionnaire d’événements.

Exemple de code 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();
    });
}
31
Horst Jahns

Modifier, mis à jour

Essayez d’utiliser les événements window.onload, document.createElement(), onload, setTimeout() avec duration défini sur 2000, en définissant src sur iframe après avoir ajouté un élément à document

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");
}

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

4
guest271314

Les PDF ont un support Javascript. J'avais besoin de fonctionnalités d'impression automatique lorsqu'un fichier généré par PHP PDF était créé et que je pouvais utiliser FPDF pour le faire fonctionner:

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

2
vrtech77

@ clarkk, je recommanderais d'utiliser quelque chose de plus puissant qui a été couvert par beaucoup de gens, ma suggestion est d'utiliser http://pdfmake.org/#/ .

J'ai utilisé ce pdfmake dans mes datatables et cela fonctionne absolument parfait. Gardez à l'esprit si vous imprimez plus de 10 000 lignes à partir de tables ou si quelque chose n'épuise pas la mémoire du navigateur :)

Je ne l'utilise plus depuis un moment, mais c'est ce que j'avais l'habitude de faire pour imprimer des pdf à partir d'un iframe ...

function printfile() {
    window.frames['objAdobePrint'].focus();
    window.frames['objAdobePrint'].print();
}

<iframe src="urlOfPdf" name="objAdobePrint" id="objAdobePrint"></iframe>
<button onclick="printfile();">Print</button>
0
raphie

Vous pouvez implémenter une fonction d'impression sans créer de nouvelle iframe (uniquement avec css) pour éviter les problèmes de sécurité:

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();
0
Pedram