在 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 正常工作,需要在系统中预先安装node和npm 。
- 项目结构:
示例:我们将首先按照给定的步骤构建基本的电子应用程序。
- 第 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 文件的页面大小。值可以是A3 、 A4 、 A5 、 Legal 、 Letter 、 Tabloid 。它还可以包含一个 Object ,其中包含以microns定义的height属性和width属性。
- printBackground:布尔型(可选)是否在 PDF 文件中包含 CSS 背景(例如background-color )。默认值为false 。
- printSelectionOnly:布尔型(可选)是否仅在 PDF 文件中打印选择或突出显示。默认值为false 。
- Landscape: Boolean (可选)指定 PDF 文件的模式。横向模式的值设置为true 。对于肖像模式,值设置为false 。默认值为false 。
- marginsType:整数(可选)指定要在 PDF 文件中使用的边距类型。它可以保存以下值:
- BrowserWindow.getAllWindows():此方法返回活动/打开的BrowserWindow实例的数组。在这个应用程序中,我们只有一个活动的 BrowserWindow实例,它可以直接从 Array 中引用,如代码所示。
- BrowserWindow.getFocusedWindow():此方法返回在应用程序中聚焦的BrowserWindow实例。如果没有找到当前BrowserWindow实例,则返回null 。在这个应用程序中,我们只有一个活动的 BrowserWindow实例,可以直接使用该方法引用它,如代码所示。
- options: Object我们可以传递一个空的选项对象,在这种情况下它将采用所有各自的默认值。它接受以下参数,
- 方法 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中返回的数据是空的。有关更多详细信息,请参阅此链接。
输出: