Drukuj PDF bezpośrednio z JavaScript

94

Buduję listę plików PDF w HTML. Na liście chciałbym zamieścić link do pobrania i przycisk / łącze drukowania. Czy istnieje sposób na bezpośrednie otwarcie okna dialogowego Drukuj dla pliku PDF, bez oglądania pliku PDF przez użytkownika lub otwierania przeglądarki PDF?

Jakieś warianty pobierania pliku PDF do ukrytego elementu iframe i uruchamiania go do drukowania za pomocą JavaScript?

Craig Celeste
źródło

Odpowiedzi:

57

Na podstawie poniższych komentarzy nie działa już w nowoczesnych przeglądarkach
To pytanie pokazuje podejście, które może być pomocne: Ciche drukowanie osadzonego pliku PDF

Używa <embed>tagu do osadzenia pliku PDF w dokumencie:

<embed
    type="application/pdf"
    src="path_to_pdf_document.pdf"
    id="pdfDocument"
    width="100%"
    height="100%" />

Następnie wywołujesz .print()metodę na elemencie w JavaScript, gdy ładowany jest plik PDF:

function printDocument(documentId) {
    var doc = document.getElementById(documentId);

    //Wait until PDF is ready to print    
    if (typeof doc.print === 'undefined') {    
        setTimeout(function(){printDocument(documentId);}, 1000);
    } else {
        doc.print();
    }
}

Możesz umieścić element osadzony w ukrytej ramce iframe i wydrukować go stamtąd, zapewniając bezproblemowe działanie.

nieważność
źródło
3
To rozwiązanie nie działa ... Odmowa
dostępu
8
To nie zadziała, jeśli osadzony dokument znajduje się w innej domenie.
nieważność
5
Łatwiej jest po prostu dodać javascript do pliku PDF, aby wydrukować po renderowaniu. To właśnie robią Dokumenty Google. W ten sposób albo przeglądarka ładuje i drukuje, albo wtyczka Adobe.
Rahly
2
Prawdopodobnie mógłbyś go wygooglować, ale wszystko to jest nowym obiektem skryptu dodanym do pliku PDF, w którym javascript to po prostu „window.print ()”
Rahly
6
Tak, mam problem we wszystkich przeglądarkach, w których metoda print () jest niezdefiniowana. Czy ta metoda jest przestarzała? Czy są jakieś inne rozwiązania?
Jacob Ensor
40

Oto funkcja drukowania pliku PDF z elementu iframe.

Musisz tylko przekazać adres URL pliku PDF do funkcji. Utworzy ramkę iframe i uruchomi drukowanie po załadowaniu pliku PDF.

Zwróć uwagę, że funkcja nie niszczy elementu iframe. Zamiast tego używa go ponownie za każdym razem, gdy funkcja jest wywoływana. Trudno jest zniszczyć element iframe, ponieważ jest potrzebny do zakończenia drukowania, a metoda drukowania nie obsługuje wywołań zwrotnych (o ile wiem).

printPdf = function (url) {
  var iframe = this._printIframe;
  if (!this._printIframe) {
    iframe = this._printIframe = document.createElement('iframe');
    document.body.appendChild(iframe);

    iframe.style.display = 'none';
    iframe.onload = function() {
      setTimeout(function() {
        iframe.focus();
        iframe.contentWindow.print();
      }, 1);
    };
  }

  iframe.src = url;
}
Nicolas BADIA
źródło
3
Dziękuję Ci, ponieważ pomagasz mi rozwiązać duży problem: bez setTimeoutfunkcji drukowania czasami zawodzi. Nie mam pojęcia, dlaczego i mam nadzieję, że ktoś się o tym dowie.
Evan Hu
Metoda print obsługuje wywołania zwrotne, ale nie była jeszcze szeroko obsługiwana, kiedy pisałeś tę odpowiedź w 2014 roku. Ale teraz jest; najnowsze wersje wszystkich głównych przeglądarek komputerowych onafterprint. Trochę obawiam się, że ponowne użycie elementu iframe może wprowadzić warunki wyścigu, w których ktoś szybko klika dwa przyciski i kończy się dwukrotnym wydrukowaniem drugiego pliku PDF, ponieważ adres URL elementu iframe został już zamieniony przed pojawieniem się pierwszego okna dialogowego drukowania.
Mark Amery,
18

Pobierz Print.js ze strony http://printjs.crabbly.com/

$http({
    url: "",
    method: "GET",
    headers: {
        "Content-type": "application/pdf"
    },
    responseType: "arraybuffer"
}).success(function (data, status, headers, config) {
    var pdfFile = new Blob([data], {
        type: "application/pdf"
    });
    var pdfUrl = URL.createObjectURL(pdfFile);
    //window.open(pdfUrl);
    printJS(pdfUrl);
    //var printwWindow = $window.open(pdfUrl);
    //printwWindow.print();
}).error(function (data, status, headers, config) {
    alert("Sorry, something went wrong")
});
user1892203
źródło
4
Nie drukuje plików PDF w przeglądarce IE, Edge ani Firefox.
Richard Collette
Wypróbowałem to dzisiaj, używając jQuery get, aby pobrać bajty pliku PDF z serwera, a następnie utworzyłem obiekt blob i „createOvjectURL” jak powyżej. PrintJS nie wyświetla w tym przypadku okna dialogowego drukowania. :)
woohoo
czy mogę wydrukować wiele plików PDF jednym kliknięciem?
Sunil Garg
12

https://github.com/mozilla/pdf.js/

do demonstracji na żywo http://mozilla.github.io/pdf.js/

prawdopodobnie tego chcesz, ale nie widzę sensu, ponieważ nowoczesne przeglądarki zawierają taką funkcjonalność, a także będzie działać strasznie wolno na urządzeniach o niskim poborze mocy, takich jak urządzenia mobilne, które, nawiasem mówiąc, mają własne zoptymalizowane wtyczki i aplikacje .

user2311177
źródło
Pdf.js jest również strasznie powolny podczas drukowania dużych dokumentów, takich jak 80 MB +
Rudolf Dvoracek
6

Użyłem tej funkcji do pobrania strumienia pdf z serwera.

function printPdf(url) {
        var iframe = document.createElement('iframe');
        // iframe.id = 'pdfIframe'
        iframe.className='pdfIframe'
        document.body.appendChild(iframe);
        iframe.style.display = 'none';
        iframe.onload = function () {
            setTimeout(function () {
                iframe.focus();
                iframe.contentWindow.print();
                URL.revokeObjectURL(url)
                // document.body.removeChild(iframe)
            }, 1);
        };
        iframe.src = url;
        // URL.revokeObjectURL(url)
    }
Adnan shah
źródło
5

Rozwiązanie dla różnych przeglądarek do drukowania plików PDF z ciągu base64:

  • Chrome: okno drukowania jest otwarte
  • FF: otwiera się nowa zakładka z pdfem
  • IE11: otwiera się monit otwórz / zapisz

.

const blobPdfFromBase64String = base64String => {
   const byteArray = Uint8Array.from(
     atob(base64String)
       .split('')
       .map(char => char.charCodeAt(0))
   );
  return new Blob([byteArray], { type: 'application/pdf' });
};

const isIE11 = !!(window.navigator && window.navigator.msSaveOrOpenBlob); // or however you want to check it

const printPDF = blob => {
   try {
     isIE11
       ? window.navigator.msSaveOrOpenBlob(blob, 'documents.pdf')
       : printJS(URL.createObjectURL(blob)); // http://printjs.crabbly.com/
   } catch (e) {
     throw PDFError;
   }
};

printPDF(blobPdfFromBase64String(base64String))

BONUS - Otwieranie pliku blob w nowej karcie dla IE11

Jeśli jesteś w stanie wykonać wstępne przetwarzanie ciągu base64 na serwerze, możesz go ujawnić pod jakimś adresem URL i użyć linku w printJS:)

Papi
źródło