Generar PDF en ElectronJS

ElectronJS es un marco de código abierto que se utiliza para crear aplicaciones de escritorio nativas multiplataforma utilizando tecnologías web como HTML, CSS y JavaScript que pueden ejecutarse en los sistemas operativos Windows, macOS y Linux. Combina el motor Chromium y NodeJS en un solo tiempo de ejecución.
En ciertas aplicaciones de escritorio, a los desarrolladores les gustaría proporcionar una función en la que el usuario pueda descargar el contenido de la página y guardarlo como un archivo PDF en su sistema. Por ejemplo, en una aplicación bancaria, al usuario le gustaría descargar su estado de cuenta que se muestra en la pantalla y guardarlo como un archivo PDF. Electron proporciona una forma en la que podemos lograr esta funcionalidad utilizando el objeto BrowserWindow y webContentspropiedad. La propiedad webContents nos proporciona ciertos eventos de instancia y métodos mediante los cuales podemos convertir el contenido de BrowserWindow que se muestra en un archivo PDF o guardar el contenido de una URL remota en un archivo PDF. Este tutorial demostrará cómo generar archivos PDF en Electron.
Suponemos que está familiarizado con los requisitos previos que se describen en el enlace mencionado anteriormente. Para que Electron funcione, node y npm deben estar preinstalados en el sistema.
 

  • Estructura del proyecto:

Project Structure

Ejemplo: Comenzaremos construyendo la aplicación electrónica básica siguiendo los pasos dados.

  • Paso 1: navegue a un directorio vacío para configurar el proyecto y ejecute el siguiente comando,
npm init

  • Para generar el archivo package.json . Instale Electron usando npm si no está instalado.
npm install electron --save

  • Este comando también creará el archivo package-lock.json e instalará las dependencias requeridas de node_modules . Cree la carpeta de activos según la estructura del proyecto. Guardaremos los archivos PDF generados en esta carpeta.

    paquete.json:

{
  "name": "electron-pdf",
  "version": "1.0.0",
  "description": "Generate PDF in Electron",
  "main": "main.js",
  "scripts": {
    "start": "electron ."
  },
  "keywords": [
    "electron"
  ],
  "author": "Radhesh Khanna",
  "license": "ISC",
  "dependencies": {
    "electron": "^8.2.5"
  }
}
  • Paso 2: Cree un archivo main.js de acuerdo con la estructura del proyecto. Este archivo es el Proceso Principal y actúa como un punto de entrada a la aplicación. Copie el código Boilerplate para el archivo main.js como se indica en el siguiente enlace . Hemos modificado el código para adaptarlo a las necesidades de nuestro proyecto.

    principal.js:

const { app, BrowserWindow } = require('electron')
  
function createWindow () {
  // Create the browser window.
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true,
      //allows remote module
      enableRemoteModule: true
    }
  })
  
  // Load the index.html of the app.
  win.loadFile('src/index.html')
  
  // Open the DevTools.
  win.webContents.openDevTools()
}
  
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
// This method is equivalent to 'app.on('ready', function())'
app.whenReady().then(createWindow)
  
// Quit when all windows are closed.
app.on('window-all-closed', () => {
  // On macOS it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {
    app.quit()
  }
})
  
app.on('activate', () => {
    // On macOS it's common to re-create a window in the 
    // app when the dock icon is clicked and there are no 
    // other windows open.
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow()
  }
})
  
// In this file, you can include the rest of your 
// app's specific main process code. You can also 
// put them in separate files and require them here.
  • Paso 3: Cree el archivo index.html y el archivo index.js dentro del directorio src . También copiaremos el código repetitivo para el archivo index.html del enlace mencionado anteriormente. Hemos modificado el código para adaptarlo a las necesidades de nuestro proyecto.
    índice.html:
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
    <!-- https://electronjs.org/docs/tutorial
                           /security#csp-meta-tag -->
    <meta http-equiv="Content-Security-Policy" 
          content="script-src 'self' 'unsafe-inline';" />
  </head>
  <body>
    <h1>Hello World!</h1>
    We are using node 
    <script>
        document.write(process.versions.node)
    </script>, Chrome 
    <script>
        document.write(process.versions.chrome)
    </script>, and Electron 
    <script>
        document.write(process.versions.electron)
    </script>.
      
     <!-- Adding Individual Renderer Process JS File -->
    <script src="index.js"></script>
  </body>
</html>
  • Salida: en este punto, nuestra aplicación electrónica básica está configurada. Para iniciar la aplicación Electron, ejecute el comando:
npm start

GUI Output

Generar PDF en Electron: la instancia de BrowserWindow y la propiedad webContents son parte del proceso principal . Para importar y usar BrowserWindow en el proceso Renderer , usaremos el módulo remoto Electron .

  • Enfoque 1: Convierta el contenido de la instancia activa actual de BrowserWindow y guárdelo como un archivo PDF. 
    index.html : agregue el siguiente fragmento en ese archivo.
<br><br>
   <button id="pdf">
     Convert Current BrowserWindow to PDF
   </button>
  • index.js : agregue el siguiente fragmento en ese archivo.
const electron = require('electron');
const path = require('path');
const fs = require('fs');
  
// Importing BrowserWindow from Main
const BrowserWindow = electron.remote.BrowserWindow;
  
var pdf = document.getElementById('pdf');
var filepath1 = path.join(__dirname, '../assets/print1.pdf'); 
  
var options = {
    marginsType: 0,
    pageSize: 'A4',
    printBackground: true,
    printSelectionOnly: false,
    landscape: false
}
  
pdf.addEventListener('click', (event) => {
  
    // let win = BrowserWindow.getAllWindows()[0];
    let win = BrowserWindow.getFocusedWindow();
      
    win.webContents.printToPDF(options).then(data => {
        fs.writeFile(filepath1, data, function (err) {
            if (err) {
                console.log(err);
            } else {
                console.log('PDF Generated Successfully');
            }
        });
    }).catch(error => {
        console.log(error)
    });
});
  • El método webContents.printToPDF(options) imprime el contenido de BrowserWindow como un PDF con la configuración personalizada de impresión de vista previa de Chromium. Este método devuelve una promesa y se resuelve en un búfer que contiene los datos que se escribirán en el archivo PDF. Toma los siguientes parámetros. Para obtener información más detallada sobre el método webContents.printToPDF() , consulte este enlace
    • opciones: Objeto Podemos pasar un objeto de opciones vacío en cuyo caso tomará todos los valores predeterminados respectivos. Toma los siguientes parámetros, 
      • marginsType: Integer (Opcional) Especifica el tipo de márgenes que se utilizarán en el archivo PDF. Puede contener los siguientes valores:
        • 0 – Márgenes predeterminados
        • 1 – Sin márgenes
        • 2 – Márgenes Mínimos
      • pageSize: Object/String (Opcional) Especifica el tamaño de página de los archivos PDF generados. Los valores pueden ser A3 , A4 , A5 , Legal , Carta , Tabloide . También puede contener un objeto que contenga la propiedad de altura y la propiedad de ancho definidas en micras .
      • printBackground: booleano (opcional) si incluir los fondos CSS (como color de fondo ) en el archivo PDF. El valor predeterminado es falso .
      • printSelectionOnly: Booleano (opcional) Si se imprimen selecciones o resaltados solo en el archivo PDF. El valor predeterminado es falso .
      • horizontal: booleano (opcional) Especifica el modo del archivo PDF. El valor se establece en verdadero para el modo horizontal . El valor se establece como falso para el modo retrato . El valor predeterminado es falso .
    • BrowserWindow.getAllWindows(): este método devuelve una array de instancias de BrowserWindow activas/abiertas . En esta aplicación, solo tenemos una instancia de BrowserWindow activa y se puede consultar directamente desde el arreglo, como se muestra en el código.
    • BrowserWindow.getFocusedWindow(): este método devuelve la instancia de BrowserWindow que está enfocada en la aplicación. Si no se encuentra ninguna instancia de BrowserWindow actual , devuelve nulo . En esta aplicación, solo tenemos una instancia de BrowserWindow activa y se puede hacer referencia directamente mediante este método, como se muestra en el código.
  • Enfoque 2: Convierta el contenido de una URL remota y guárdelo como un archivo PDF. 
    index.html : agregue el siguiente fragmento en ese archivo.
<br><br>
    <button id="convert">Convert Google.com to PDF</button>
  • index.js : agregue el siguiente fragmento en ese archivo.
const electron = require('electron');
const path = require('path');
const fs = require('fs');
// Importing BrowserWindow from Main
const BrowserWindow = electron.remote.BrowserWindow;
  
var convert = document.getElementById('convert');
var filepath2 = path.join(__dirname, '../assets/print2.pdf'); 
  
var options2 = {
    marginsType: 1,
    pageSize: 'A4',
    printBackground: true,
    printSelectionOnly: false,
    landscape: false
}
  
convert.addEventListener('click', (event) => {
    let win = new BrowserWindow({
        show: false,
        webPreferences: {
          nodeIntegration: true
        }
      });
  
    win.loadURL('https://www.google.com/');
  
    win.webContents.on('did-finish-load', () => {
        win.webContents.printToPDF(options2).then(data => {
            fs.writeFile(filepath2, data, function (err) {
                if (err) {
                    console.log(err);
                } else {
                    console.log('PDF Generated Successfully');
                }
            });
        }).catch(error => {
            console.log(error)
        });
    });
});
  • En este caso, creamos una nueva instancia de BrowserWindow y establecimos la propiedad show en false . Por lo tanto, la ventana recién creada nunca se mostrará. Hemos utilizado el método win.loadURL(ruta) para cargar el contenido de la URL externa en BrowserWindow . La ruta de URL puede ser una dirección remota especificada por el protocolo http:// o una ruta a un archivo en el sistema local especificado mediante el protocolo file:// . Este método devuelve una Promesa y se resuelve cuando la página ha terminado de cargarse y el evento did-finish-load de webContentsse emite la propiedad. Para obtener información más detallada, consulte este enlace .
    El evento de instancia did-finish-load pertenece a la propiedad webContents . Se emite cuando finaliza la navegación y la página está completamente cargada. Esto sucede cuando el control giratorio de la página deja de girar y se envía el evento de carga . En caso de que no se utilice este emisor de eventos y se llame al método webContents.printToPDF() , el PDF generado será un documento en blanco ya que el contenido no terminó de cargarse en BrowserWindow . Por lo tanto, los datos devueltos en la Promesa están vacíos. Para obtener información más detallada, consulte este enlace
    Producción:
     

Publicación traducida automáticamente

Artículo escrito por radheshkhanna y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *