📜  在 ElectronJS 中生成 PDF

📅  最后修改于: 2022-05-13 01:56:35.387000             🧑  作者: Mango

在 ElectronJS 中生成 PDF

ElectronJS是一个开源框架,用于使用能够在 Windows、macOS 和 Linux 操作系统上运行的 HTML、CSS 和 JavaScript 等 Web 技术构建跨平台原生桌面应用程序。它将 Chromium 引擎和NodeJS组合成一个单一的运行时。
在某些桌面应用程序中,开发人员希望提供一种功能,用户可以在其中下载页面内容并将其作为 PDF 文件保存到他们的系统中。例如,在银行应用程序中,用户希望下载他/她在屏幕上显示的帐户对帐单并将其保存为 PDF 文件。 Electron 提供了一种方法,我们可以使用BrowserWindow对象和webContents属性来实现此功能。 webContents属性为我们提供了某些实例事件和方法,通过它们我们可以将正在显示的BrowserWindow的内容转换为 PDF 文件或将远程 URL 的内容保存为 PDF 文件。本教程将演示如何在 Electron 中生成 PDF 文件。
我们假设您熟悉上述链接中涵盖的先决条件。为了使 Electron 正常工作,需要在系统中预先安装nodenpm

  • 项目结构:

项目结构

示例:我们将首先按照给定的步骤构建基本的电子应用程序。

  • 第 1 步:导航到空目录以设置项目,然后运行以下命令,
npm init

  • 生成package.json文件。如果没有安装Electron ,请使用 npm 安装。
npm install electron --save

  • 此命令还将创建package-lock.json文件并安装所需的node_modules依赖项。根据项目结构创建assets文件夹。我们将生成的 PDF 文件保存到该文件夹中。

    包.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"
  }
}
  • 第二步:根据项目结构创建一个main.js文件。该文件是主进程并充当应用程序的入口点。复制以下链接中给出的main.js文件的样板代码。我们已经修改了代码以满足我们的项目需求。

    主.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.
  • 第三步:src目录下创建index.html文件和index.js文件。我们还将从上述链接复制index.html文件的样板代码。我们已经修改了代码以满足我们的项目需求。
    索引.html:


  
    
    Hello World!
    
    
  
  
    

Hello World!

    We are using node      , Chrome      , and Electron      .                     
  • 输出:此时,我们的基本电子应用程序已设置完毕。要启动 Electron 应用程序,请运行以下命令:
npm start

图形用户界面输出

在 Electron 中生成 PDF: BrowserWindow实例和webContents属性是Main Process的一部分。要在渲染器进程中导入和使用BrowserWindow ,我们将使用 Electron远程模块。

  • 方法一:将当前活动的BrowserWindow Instance 的内容转换为 PDF 文件。
    index.html :在该文件中添加以下代码段。


   
  • index.js :在该文件中添加以下代码段。
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)
    });
});
  • webContents.printToPDF(options)方法使用 Chromium 的预览打印自定义设置将BrowserWindow内容打印为 PDF。此方法返回一个Promise并解析为包含要写入 PDF 文件的数据的Buffer 。它接受以下参数。有关webContents.printToPDF()方法的更多详细信息,请参阅此链接。
    • options: Object我们可以传递一个空的选项对象,在这种情况下它将采用所有各自的默认值。它接受以下参数,
      • marginsType:整数(可选)指定要在 PDF 文件中使用的边距类型。它可以保存以下值:
        • 0 – 默认边距
        • 1 – 无边距
        • 2 – 最低保证金
      • pageSize:对象/字符串(可选)指定生成的 PDF 文件的页面大小。值可以是A3A4A5LegalLetterTabloid 。它还可以包含一个 Object ,其中包含以microns定义的height属性和width属性。
      • printBackground:布尔型(可选)是否在 PDF 文件中包含 CSS 背景(例如background-color )。默认值为false
      • printSelectionOnly:布尔型(可选)是否仅在 PDF 文件中打印选择或突出显示。默认值为false
      • Landscape: Boolean (可选)指定 PDF 文件的模式。横向模式的值设置为true 。对于肖像模式,值设置为false 。默认值为false
    • BrowserWindow.getAllWindows():此方法返回活动/打开的BrowserWindow实例的数组。在这个应用程序中,我们只有一个活动的 BrowserWindow实例,它可以直接从 Array 中引用,如代码所示。
    • BrowserWindow.getFocusedWindow():此方法返回在应用程序中聚焦的BrowserWindow实例。如果没有找到当前BrowserWindow实例,则返回null 。在这个应用程序中,我们只有一个活动的 BrowserWindow实例,可以直接使用该方法引用它,如代码所示。
  • 方法 2:转换远程 URL 的内容并将其保存为 PDF 文件。
    index.html :在该文件中添加以下代码段。


    
  • index.js :在该文件中添加以下代码段。
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)
        });
    });
});
  • 在这种情况下,我们创建了一个新的 BrowserWindow实例并将show属性设置为false 。因此,新创建的窗口将永远不会显示。我们使用win.loadURL(path)方法在BrowserWindow中加载外部 URL 的内容。 url路径可以是http://协议指定的远程地址,也可以是file://协议指定的本地系统中文件的路径。此方法返回一个Promise ,并在页面完成加载并且 webContents 属性的did-finish-load事件为Emitted时解决。有关更多详细信息,请参阅此链接。
    did-finish-load实例事件属于webContents属性。它在导航完成并且页面完全加载时发出。当页面的微调器停止旋转并且onload事件已被调度时,就会发生这种情况。如果未使用此事件发射器并且调用了webContents.printToPDF()方法,则生成的 PDF 将是一个空白文档,因为内容未在BrowserWindow中完成加载。因此Promise中返回的数据是空的。有关更多详细信息,请参阅此链接。
    输出: