with tutorial print made imprimir first examples con apps app javascript node.js pdf printing electron

javascript - tutorial - gmail electron app



Imprimiendo un archivo PDF con Electron JS (5)

Estoy intentando crear una aplicación Electron JS que tiene el propósito de imprimir archivos PDF de tamaño carta.

Este es mi fragmento de código para imprimir:

win = new BrowserWindow({ width: 378, height: 566, show: true, webPreferences: { webSecurity: false, plugins: true } }); // load PDF win.loadURL(''file://'' + __dirname + ''/header1_X_BTR.pdf''); // if pdf is loaded start printing win.webContents.on(''did-finish-load'', () => { win.webContents.print({silent: true, printBackground:true}); });

Mis problemas son: si tengo print({silent:true}) mi impresora imprime una página vacía. Si tengo print({silent:false}) , la impresora imprime de la misma manera que la captura de pantalla, con encabezados, controles, etc.

Necesito una impresión silenciosa del contenido PDF, y no puedo hacerlo durante días. ¿Alguien experimentó lo mismo con Electron?


Así que parece que está intentando descargar el archivo pdf en lugar de imprimir un pdf de la pantalla actual, que es lo que intenta print . Como tal, tienes un par de opciones.

1) Deshabilite el visor de pdf nativo en electron:

Si no le importa la ventana electrónica que muestra el pdf, deshabilitar el visor de PDF nativo en electron debería hacer que trate el archivo como una descarga e intente descargarlo.

new BrowserWindow({ webPreferences: { plugins: false } })

También es posible que desee revisar la API de DownloadItem de la electrónica para realizar una manipulación en el lugar donde se guardará el archivo.

2) Descarga el pdf a través de alguna otra api.

No voy a dar ninguna información específica para este porque deberías poder encontrar información sobre esto por ti mismo, pero básicamente, si quieres descargar el archivo de algún lugar, puedes usar otra API de descarga como una biblioteca AJAX para descargar. El archivo y guardarlo en algún lugar. Esto también podría permitirle procesar el documento en una ventana electrónica, ya que una vez que inicie la descarga, probablemente pueda redirigir la ventana a la URL del pdf y hacer que el visor nativo lo maneje.

En pocas palabras, me parece que realmente no quieres imprimir desde un electrón, solo quieres guardar el archivo pdf que estás mostrando. La impresión desde un electrón mostrará lo que ve en la pantalla, no el documento PDF en sí mismo, así que creo que no entendió bien cuál era el objetivo de la impresión. Esperemos que esto te ayude, buena suerte!

=== EDIT ===

Desafortunadamente, no creo que haya una forma de imprimir el archivo directamente desde un electrón, ya que la impresión electrónica es para imprimir el contenido de la pantalla de electrones. Pero debería poder descargar el archivo a través de una simple solicitud para el archivo (ver arriba).

Mi recomendación para usted sería crear una página para obtener una vista previa del archivo. Esta sería una página independiente, no la incorporada en el visor de pdf. Luego puede insertar un botón en algún lugar de la página para descargar el pdf a través de algunos medios y omitir cualquier solicitud de ubicación de guardado (esto debería ser lo suficientemente fácil como para encontrar la documentación).

Luego, para tener su vista previa, en la misma página puede tener una etiqueta webview en su página, que mostrará el visor de pdf nativo. Para que el visor de PDF nativo funcione en la etiqueta webview, debe incluir el atributo de plugins en la etiqueta. Es una etiqueta booleana, por lo que su mera presencia es todo lo que se necesita, como <webview ... plugins> Esto activa el soporte de plugin para el renderizador de webview que se requiere para el visor de pdf.

Puede modificar el estilo de tamaño de esta etiqueta en la página que desee para satisfacer sus necesidades. Un truco para deshacerse de las opciones de descarga e impresión para que un usuario no pueda presionarlas es agregar #toolbar=0 al final de la URL del pdf para evitar que el visor de PDF nativo muestre la barra de herramientas superior con estos botones.

De esta manera, puede tener su vista previa, asegurarse de que el usuario no puede usar la descarga integrada o imprimir desde el visor de pdf con la interfaz de usuario adicional, y puede agregar otro botón para descargarla para poder imprimirla más tarde.


Dado que está utilizando contents.print([options], [callback]) asumiré que desea imprimir en papel y no en su Disco.

La respuesta a su problema es simple. Es el evento que estás escuchando el que está causando el error. Así que si simplemente haces esto:

winObject.webContents.on(''did-frame-finish-load'', () => { setTimeout(() => {winObject.webContents.print({silent: true, printBackground:true})}, 3000); });

todo funcionará bien si la impresora predeterminada es la correcta. Hice una prueba de esto y hará su trabajo más o menos. Puede cambiar mi evento a cualquier evento que desee, la parte importante es la espera con setTimeout. El PDF que está intentando imprimir simplemente no está disponible en el marco cuando se usa silent:true .

Sin embargo, déjame entrar en detalles aquí para aclarar las cosas:

Electron cargará archivos o URL en una ventana creada ( BrowserWindow ) que está vinculada a eventos. El problema es que cada evento "puede" comportarse de manera diferente en diferentes sistemas. Tenemos que vivir con eso y no podemos cambiarlo fácilmente. Pero saber esto ayudará a mejorar el desarrollo de aplicaciones personalizadas.

Si carga urls o htmls, todo funcionará sin configurar ninguna opción personalizada. Usando PDFs como fuente tenemos que usar esto:

import electron, { BrowserWindow } from ''electron''; const win = new BrowserWindow({ // @NOTE I did keep the standard options out of this. webPreferences: { // You need this options to load pdfs plugins: true // this will enable you to use pdfs as source and not just download it. } });

webPreferences: { plugins: true } : sin webPreferences: { plugins: true } se descargará el PDF de origen en lugar de cargarlo en la ventana.

Dicho esto, webContents tu PDF en los contenidos webContents de tu ventana. Así que tenemos que escuchar en eventos compatibles con BrowserWindow . Lo hizo todo bien, la única parte que se perdió fue que la impresión es otra interfaz.

La impresión capturará tus contenidos webContents tal como está cuando presionas "imprimir". Es muy importante saber esto cuando se trabaja con impresoras. Porque si algo se carga un poco más en un sistema diferente, por ejemplo, el visor de PDF seguirá siendo de color gris oscuro sin las letras, entonces su impresión imprimirá el fondo gris oscuro o incluso los botones.

Ese pequeño problema se soluciona fácilmente con setTimeout() .

Preguntas y respuestas útiles para imprimir con electrón:

Sin embargo, hay muchos más problemas posibles con la impresión, ya que la mayoría del código está detrás de puertas cerradas sin que se utilicen API en todo el mundo. Solo tenga en cuenta que cada impresora puede comportarse de manera diferente, por lo que la prueba en más máquinas ayudará.


Estoy enfrentando el mismo problema. Parece que la impresión de PDF en una impresora simplemente no está implementada en Electron, a pesar de que se ha solicitado desde 2017. Aquí hay otra pregunta relacionada con SO y la solicitud de características en GitHub:

Una posible solución podría ser utilizar Google PDFium y una biblioteca de NodeJS que parece permitir la conversión de PDF a un conjunto de EMF, por lo que los EMF pueden imprimirse en una impresora local / de red, al menos en Windows.

Como otra opción viable, esta respuesta proporciona una solución C # simple para la impresión de PDF utilizando PdfiumViewer , que es una biblioteca de envoltorios de PDFium para .NET.

Estoy mirando cualquier otra opción. Utilizar una instancia localmente instalada de Acrobat Reader para imprimir no es una solución aceptable para nosotros.

ACTUALIZADO. Por ahora, PDF.js resuelve el problema con la visualización / vista previa de páginas individuales, pero en cuanto a la impresión en sí misma, parece que Electron (en el momento de esta publicación) solo carece de las API de impresión adecuadas. Por ejemplo, no puede configurar el tamaño del papel / modo de retrato horizontal, etc. Además, al imprimir, PDF.js produce impresiones rasterizadas, gracias a cómo funciona el lienzo de HTML5, a diferencia de cómo lo hace Chrome PDF Viewer. Aquí hay una discusión de algunas otras deficiencias de PDF.js.

Entonces, por ahora, creo que podríamos continuar con una combinación de PDF.js (para la interfaz de usuario en el proceso del Renderizador de Electron) y PDFium (para la impresión real desde el proceso Principal).

Basado en la respuesta de Tim , aquí hay una versión del renderizador PDF.js que usa ES8 async/await await (compatible a partir de la versión actual de Electron):

async function renderPDF(url, canvasContainer, options) { options = options || { scale: 1 }; async function renderPage(page) { let viewport = page.getViewport(options.scale); let canvas = document.createElement(''canvas''); let ctx = canvas.getContext(''2d''); let renderContext = { canvasContext: ctx, viewport: viewport }; canvas.height = viewport.height; canvas.width = viewport.width; canvasContainer.appendChild(canvas); await page.render(renderContext); } let pdfDoc = await pdfjsLib.getDocument(url); for (let num = 1; num <= pdfDoc.numPages; num++) { if (num > 1) { // page separator canvasContainer.appendChild(document.createElement(''hr'')); } let page = await pdfDoc.getPage(num); await renderPage(page); } }


La forma más sencilla de hacerlo es renderizar las páginas PDF a elementos individuales del lienzo en una página utilizando PDF.js y luego imprimir.

Arreglé esta idea para usar la versión PDF.js (v1) para la que fue diseñada y es probablemente un buen punto de partida.

Esto es esencialmente lo que está haciendo el visor de pdf de electron / chrome pero ahora tienes control total sobre el diseño.

<html> <body> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/1.10.90/pdf.js"></script> <script type="text/javascript"> function renderPDF(url, canvasContainer, options) { var options = options || { scale: 1 }; function renderPage(page) { var viewport = page.getViewport(options.scale); var canvas = document.createElement(''canvas''); var ctx = canvas.getContext(''2d''); var renderContext = { canvasContext: ctx, viewport: viewport }; canvas.height = viewport.height; canvas.width = viewport.width; canvasContainer.appendChild(canvas); page.render(renderContext); } function renderPages(pdfDoc) { for(var num = 1; num <= pdfDoc.numPages; num++) pdfDoc.getPage(num).then(renderPage); } PDFJS.disableWorker = true; PDFJS.getDocument(url).then(renderPages); } </script> <div id="holder"></div> <script type="text/javascript"> renderPDF(''//cdn.mozilla.net/pdfjs/helloworld.pdf'', document.getElementById(''holder'')); </script> </body> </html>


Si ya tiene el archivo pdf o lo guarda antes de imprimir "Supongo que lo es", entonces puede tomar la ubicación del archivo y luego puede usar el proceso externo para realizar la impresión usando child_process .

Puedes usar el lp command o PDFtoPrinter para Windows

const ch = require(''os''); switch (process.platform) { case ''darwin'': case ''linux'': ch.exec( ''lp '' + pdf.filename, (e) => { if (e) { throw e; } }); break; case ''win32'': ch.exec( ''ptp '' + pdf.filename, { windowsHide: true }, (e) => { if (e) { throw e; } }); break; default: throw new Error( ''Platform not supported.'' ); }

Espero que ayude.

Edición: También puede usar SumatraPDF para Windows https://github.com/sumatrapdfreader/sumatrapdf