Imprimir PDF diretamente do JavaScript

93

Estou construindo uma lista de PDFs em HTML. Na lista, gostaria de incluir um link de download e um botão / link de impressão. Existe alguma maneira de abrir diretamente a caixa de diálogo Imprimir para o PDF sem que o usuário veja o PDF ou abra um visualizador de PDF?

Alguma variação de baixar o PDF em um iframe oculto e acioná-lo para impressão com JavaScript?

Craig Celeste
fonte

Respostas:

56

Com base nos comentários abaixo, ele não funciona mais em navegadores modernos.
Esta pergunta demonstra uma abordagem que pode ser útil para você: Impressão silenciosa de um PDF incorporado

Ele usa a <embed>tag para incorporar o PDF ao documento:

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

Em seguida, você chama o .print()método no elemento em Javascript quando o PDF é carregado:

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

Você pode colocar o embed em um iframe oculto e imprimi-lo de lá, proporcionando uma experiência perfeita.

nulidade
fonte
3
Esta solução não funciona ... Estou recebendo permissão negada para o Chrome, FF
user1428716
8
Isso não funcionará se o documento incorporado estiver em um domínio diferente.
nulidade
5
Mais fácil simplesmente adicionar javascript ao pdf para imprimir quando renderizado. Isso é o que o Google Docs faz. Desta forma, o navegador carrega e imprime ou o plugin Adobe.
Rahly,
2
Você provavelmente poderia pesquisar no Google, mas tudo o que é, é um novo objeto de script adicionado ao pdf, onde o javascript é apenas "window.print ()"
Rahly
6
Sim, estou tendo o problema em todos os navegadores onde o método print () é indefinido. Este método está desatualizado? Existem outras soluções?
Jacob Ensor
38

Esta é uma função para imprimir um PDF de um iframe.

Você só precisa passar a URL do PDF para a função. Isso criará um iframe e iniciará a impressão assim que o PDF for carregado.

Observe que a função não destrói o iframe. Em vez disso, ele a reutiliza sempre que a função é chamada. É difícil destruir o iframe porque ele é necessário até que a impressão seja concluída, e o método de impressão não tem suporte de retorno de chamada (até onde eu sei).

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
fonte
3
Agradeço a você por me ajudar a resolver um grande problema: sem setTimeout, a função de impressão às vezes falha. Não faço ideia do porquê e espero que alguém descubra.
Evan Hu
O método de impressão tem suporte de retorno de chamada, mas ainda não era amplamente suportado quando você escreveu esta resposta em 2014. Mas agora é; as versões mais recentes de todos os principais navegadores de desktop suportam onafterprint. Estou um pouco preocupado com o fato de que a reutilização de um iframe pode apresentar condições de corrida em que alguém clica em dois botões rapidamente e acaba imprimindo o segundo PDF duas vezes porque o URL do iframe já havia sido trocado antes de a primeira caixa de diálogo de impressão aparecer.
Mark Amery
18

Baixe o Print.js em 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
fonte
3
Não imprime PDFs no IE, Edge ou Firefox.
Richard Collette
Tentei isso hoje usando jQuery get para obter os bytes do pdf do servidor, então criei o blob e 'createOvjectURL' como acima. PrintJS não mostra a caixa de diálogo de impressão neste caso. :)
woohoo,
posso imprimir vários arquivos PDF com um único clique?
Sunil Garg
12

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

para uma demonstração ao vivo http://mozilla.github.io/pdf.js/

é provavelmente o que você quer, mas não consigo ver o sentido disso, já que os navegadores modernos incluem essa funcionalidade, também funcionará terrivelmente lento em dispositivos de baixa potência, como dispositivos móveis que, a propósito, têm seus próprios plug-ins e aplicativos otimizados .

user2311177
fonte
Pdf.js também é terrivelmente lento ao imprimir documentos grandes, como
80 MB
6

Usei essa função para baixar o fluxo de PDF do servidor.

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
fonte
4

Solução para vários navegadores para imprimir pdf a partir de string base64:

  • Chrome: a janela de impressão é aberta
  • FF: nova guia com pdf é aberta
  • IE11: abrir / salvar prompt é aberto

.

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

BÔNUS - Abrindo arquivo blob em uma nova guia para o IE11

Se você for capaz de fazer algum pré-processamento da string base64 no servidor, poderá expô-la em alguma url e usar o link em printJS:)

Papi
fonte