2016-07-28 26 views
24

Die Sache, die ich erstellen möchte, ist, dass ich durch Klicken auf eine Schaltfläche den Druck einer PDF-Datei auslösen möchte, aber ohne es zu öffnen.Drucken Sie ein PDF, ohne es visuell zu öffnen

+-----------+ 
| Print PDF | 
+-----------+ 
    ^Click *---------> printPdf(pdfUrl) 

Die Art und Weise, wie ich es zuerst versucht, ist ein iframe zu verwenden:

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

Diese auf Safari funktioniert (Desktop & iOS) und Chrome (wir können es vielleicht verallgemeinern Webkit?).

Bei Firefox endet PDF.contentWindow.print() mit einem permission denied Fehler (sogar die PDF wird von der gleichen Domäne geladen).

Auf IE (11), der onload Handler funktioniert einfach nicht.

Jetzt ist meine Frage: gibt es eine andere bessere Möglichkeit, das pdf zu drucken, ohne es visuell dem Benutzer zu öffnen?

Die Cross-Browser-Sache ist hier kritisch. Wir sollten so viele Browser wie möglich unterstützen.

Was ist der beste Weg, dies zu erreichen? Ist mein Start ein guter? Wie vervollständige ich es?

Wir sind jetzt im Jahr 2016 und ich fühle mich wie dies ist immer noch ein Schmerz, um über die Browser zu implementieren.

+0

Wenn ich das richtig verstanden habe, möchten Sie das PDF nicht anzeigen, aber trotzdem ausdrucken ... also einfach mit anderen Worten herunterladen? Oder tun Sie einfach so, wie Sie es normalerweise tun würden, und verstecken Sie diesen Abschnitt. – Jorrex

+0

Kann die PDF-Datei beim Öffnen nicht automatisch gedruckt werden? – epascarello

+0

@Jorrex Nein, öffne es in einem versteckten Iframe und öffne den Druckdialog im Kontext dieses Iframes. Der Iframe ist keine Voraussetzung, aber es war mein erster Versuch. Ich bin mir nicht sicher, ob es andere Möglichkeiten gibt ... Kurz gesagt: Wenn ich auf die Schaltfläche klicke, sollte der Druckdialog geöffnet und das PDF gedruckt werden. –

Antwort

9

UPDATE: Dieses link Details eine elegante Lösung, die die Bearbeitung der Seiteneigenschaften für die erste Seite beinhaltet und das Hinzufügen einer Aktion auf Seite öffnen. Funktioniert in allen Browsern (da Browser das im Abschnitt Aktionen platzierte JavaScript ausführen). Benötigt Adobe Acrobat Pro.


Es scheint, dass 2016 keine neuen Fortschritte beim Druckproblem bringt. Hatte ein ähnliches Problem und um den Druck Cross-Browser zu machen, löste ich es mit PDF.JS, musste aber eine Ein-Liner-Ergänzung zu der Quelle machen (sie bitten Sie, darauf auf jeden Fall aufzubauen).

Die Idee:

  • Laden Sie die vorgefertigte stabile Version von https://mozilla.github.io/pdf.js/getting_started/#download und fügen Sie den „Build“ und „web“ Ordner für das Projekt.
  • Die viewer.html Datei ist, was PDFs mit einer reichhaltigen Schnittstelle ausgibt und Druckfunktionalität enthält. Ich habe einen Link in diese Datei zu meinem eigenen JavaScript hinzugefügt, der window.print() nach einer Verzögerung auslöst.

Der Link hinzugefügt Zuschauer:

<script src="viewer.js"></script> 
    <!-- this autoPrint.js was added below viewer.js --> 
    <script src="autoPrint.js"></script> 
</head> 

Die autoPrint.js javascript:

(function() { 
    function printWhenReady() { 
     if (PDFViewerApplication.initialized) { 
      window.print(); 
     } 
     else { 
      window.setTimeout(printWhenReady, 3000); 
     } 
    }; 

    printWhenReady(); 
})(); 
  • ich dann Anrufe viewer.html?file= im src eines iframe setzen könnte und ausblenden. Hat Sichtbarkeit zu verwenden, da Firefox nicht Arten angezeigt:

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

Das Ergebnis: Der Druckdialog zeigte nach einer kurzen Verzögerung mit dem PDF vor dem Benutzer verborgen werden.

Getestet in Chrome, IE, Firefox.

+0

Pdf.js ist definitiv eine Sache. In Bezug auf die Kompatibilität funktioniert es gut auf moderne Browser Der unangenehme Teil ist, dass es Druckfehler (verpixelte Ausgabe, falsche Schriftarten usw.) hat. Ich habe das auch versucht. –

+0

Wahr, dass. Um die Dinge vorwärts zu bewegen, räumte ich die Mängel in Pdf.js und wo möglich untergebracht von diesen Jahren pdf-Drucken wird leicht gemacht ... – Balah

+0

Können Sie bitte fügen Sie in Ihrer Antwort, dass [diese Lösung] (http://nvision.co/blog/tips-and-tricks/auto-print-pdf-file- open /) funktioniert? Browser führen js dort aus Durch Hinzufügen von 'window.print()' in der PDF wird das Problem gelöst. –

5

die letzten paar Stunden Nachdem wir versuchen, diese ein, um herauszufinden, und viele hier suchen ist, was ich festgestellt haben, ...

Die HTML5 Web API spec for Printing zeigt an, dass eine der printing stepsbeforeprint feuern muss, ein einfaches Ereignis (ein Ereignis, das nicht stornierbar ist), um das Fensterobjekt des Dokuments, das gedruckt wird (sowie alle verschachtelten Browsing-Kontexte, bezieht sich dies auf iframes), um Änderungen am Dokument vor dem Drucken zu ermöglichen. Dieser Schritt ist intern im Browser und nicht etwas, das Sie anpassen können. Während dieses Vorgangs zeigt der Druckdialog des Browsers manchmal eine Vorschau der Datei an (Chrome tut dies) ... wenn Sie also das Ziel haben, die Datei niemals dem Betrachter anzuzeigen, könnten Sie feststecken.

Die am nächsten zu erreichen, dass ich kam, war durch Erstellen einer index.html Datei, die eine Schaltfläche mit Daten hat * Attribute, die Kontext zur Verfügung gestellt. Ändern Sie den Pfad/filename.ext im Attribut data-print-resource-uri in eine eigene lokale Datei.

<!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> 

Dann in der print.js Datei, habe ich versucht, ein paar Dinge, aber nie ganz daran zu arbeiten (verschiedene Dinge verlassen ich mit in den Kommentaren gespielt hatte).

// 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(); 
    */ 
} 

Ich glaube, wenn Sie es richtig, die Blob mit Arbeit bekommen könnte, die am besten in der Cross-Browser-Methode arbeiten Sie wollten.

fand ich ein paar Hinweise zu diesem Thema, die hilfreich sein könnten:

+0

Interessanter Ansatz, aber ich sehe nicht den Unterschied zwischen der Einstellung der 'src' auf eine Blob-URL oder nur die Einstellung der Datei-URL Zumindest nach dem Beheben der kleinen Probleme auf dem Code, bekomme ich den gleichen Fehler in Firefox: 'Zugriff verweigert Zugriff auf Eigenschaft" print ". –