Imprima PDF directamente desde JavaScript

93

Estoy creando una lista de archivos PDF en HTML. En la lista me gustaría incluir un enlace de descarga y un botón / enlace de impresión. ¿Hay alguna forma de abrir directamente el cuadro de diálogo Imprimir para el PDF sin que el usuario vea el PDF o abra un visor de PDF?

¿Alguna variación de descargar el PDF en un iframe oculto y activarlo para que se imprima con JavaScript?

Craig Celeste
fuente

Respuestas:

56

Según los comentarios a continuación, ya no funciona en los navegadores modernos.Esta
pregunta demuestra un enfoque que podría serle útil: Impresión silenciosa de un PDF incrustado

Utiliza la <embed>etiqueta para incrustar el PDF en el documento:

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

Luego llama al .print()método en el elemento en Javascript cuando se carga el 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();
    }
}

Puede colocar el incrustado en un iframe oculto e imprimirlo desde allí, lo que le brinda una experiencia perfecta.

nulabilidad
fuente
3
Esta solución no funciona ... Me niegan el permiso para Chrome, FF
user1428716
8
Esto no funcionará si el documento incrustado está en un dominio diferente.
nulabilidad
5
Es más fácil simplemente agregar javascript al pdf para imprimir cuando se procesa. Esto es lo que hace Google Docs. De esta manera, el navegador lo carga e imprime, o el complemento de adobe.
Rahly
2
Probablemente podría buscarlo en Google, pero todo lo que es, es un nuevo objeto de script agregado al pdf, donde el javascript es simplemente "window.print ()"
Rahly
6
Sí, tengo el problema en todos los navegadores donde el método print () no está definido. ¿Este método está desactualizado? ¿Existen otras soluciones?
Jacob Ensor
38

Aquí hay una función para imprimir un PDF desde un iframe.

Solo necesita pasar la URL del PDF a la función. Creará un iframe y activará la impresión una vez que se cargue el PDF.

Tenga en cuenta que la función no destruye el iframe. En cambio, lo reutiliza cada vez que se llama a la función. Es difícil destruir el iframe porque es necesario hasta que se realiza la impresión y el método de impresión no tiene soporte de devolución de llamada (hasta donde yo sé).

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;
}
Nicolás BADIA
fuente
3
Le doy las gracias porque me ayuda a resolver un gran problema: sin ella setTimeout, la función de impresión fallará a veces. No tengo idea de por qué y espero que alguien lo descubra.
Evan Hu
El método de impresión tiene soporte de devolución de llamada, pero aún no era ampliamente compatible cuando escribió esta respuesta en 2014. Sin embargo, ahora lo es; las últimas versiones de los principales navegadores de escritorio son compatibles onafterprint. Me preocupa un poco que reutilizar un iframe pueda introducir condiciones de carrera en las que alguien hace clic en dos botones rápidamente y termina imprimiendo el segundo PDF dos veces porque la URL del iframe ya se había intercambiado antes de que apareciera el primer cuadro de diálogo de impresión.
Mark Amery
18

Descargue Print.js desde 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")
});
usuario1892203
fuente
3
No imprime archivos PDF en IE, Edge o Firefox.
Richard Collette
Intenté esto hoy usando jQuery para obtener los bytes del pdf del servidor, luego crear el blob y 'createOvjectURL' como se indicó anteriormente. PrintJS no muestra el diálogo de impresión en este caso. :)
woohoo
¿Puedo imprimir varios archivos PDF con un solo clic?
Sunil Garg
12

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

para una demostración en vivo http://mozilla.github.io/pdf.js/

es probablemente lo que quieres, pero no veo el sentido de esto, ya que los navegadores modernos incluyen dicha funcionalidad, también funcionará terriblemente lento en dispositivos de baja potencia como dispositivos móviles que, por cierto, tienen sus propios complementos y aplicaciones optimizados. .

usuario2311177
fuente
Pdf.js también es terriblemente lento al imprimir documentos grandes, como
80 MB
6

Usé esta función para descargar la secuencia de PDF desde el 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
fuente
4

Solución de navegador cruzado para imprimir pdf desde una cadena base64:

  • Chrome: se abre la ventana de impresión
  • FF: se abre una nueva pestaña con pdf
  • IE11: se abre el mensaje abrir / guardar

.

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: abrir un archivo blob en una nueva pestaña para IE11

Si puede hacer un preprocesamiento de la cadena base64 en el servidor, puede exponerlo en alguna URL y usar el enlace en printJS:)

Papi
fuente