Electron PDF 打印与报告导出
准备独立报告页面并使用 printToPDF 生成可保存的 PDF 文件。
🎯 引言
报告导出不是把当前窗口截图保存下来,而是准备一个适合打印的页面,再让 Electron 生成 PDF。本篇只实现最小的页面打印流程。
🧱 为什么单独准备报告页面
工作页面通常有按钮、筛选器和侧边栏,直接打印会把这些操作元素也带进报告。单独准备报告页面,可以只放标题、表格和结论,让打印样式更容易控制。
report.html
<!doctype html>
<html lang="zh-CN">
<body>
<main>
<h1>资料分析报告</h1>
<p>生成时间:2026-09-17</p>
</main>
</body>
</html>
🛠 使用 printToPDF
整个过程可以拆成 5 步:
- 创建一个不显示给用户的窗口。
- 在这个窗口里加载报告页面。
- 把报告页面转换成 PDF 数据。
- 让用户选择保存位置。
- 把 PDF 数据写入用户选择的文件,然后关闭隐藏窗口。
下面的函数只负责完成这 5 步。它应该放在主进程中,因为创建窗口、打开保存对话框和写入文件都属于桌面能力:
electron/main.js
const { BrowserWindow, dialog } = require('electron/main');
const path = require('node:path');
const { writeFile } = require('node:fs/promises');
async function exportReport() {
// 1. 创建隐藏窗口,用户不会看到这个窗口
const reportWindow = new BrowserWindow({ show: false });
try {
// 2. 让隐藏窗口加载报告页面
await reportWindow.loadFile(path.join(__dirname, 'report.html'));
// 3. 把报告页面生成 PDF 数据
const pdf = await reportWindow.webContents.printToPDF({
printBackground: true,
pageSize: 'A4',
});
// 4. 打开系统保存对话框,让用户选择文件位置
const result = await dialog.showSaveDialog({
defaultPath: '资料分析报告.pdf',
filters: [{ name: 'PDF 文件', extensions: ['pdf'] }],
});
// 用户没有取消时,result.filePath 才是有效的保存路径
if (!result.canceled) {
// 5. pdf 是一段二进制数据,把它写入选择的文件
await writeFile(result.filePath, pdf);
}
} finally {
// 无论成功还是失败,都关闭隐藏窗口
reportWindow.close();
}
}
这段函数不会自己执行,需要在用户点击“导出报告”时调用:
electron/main.js
await exportReport();
printToPDF() 返回的不是文件路径,而是 PDF 的二进制数据;showSaveDialog() 返回用户选择的路径;writeFile() 才真正把 PDF 保存到磁盘。
如果报告页面包含网络字体或图片,要在调用 printToPDF() 前等待它们加载完成,否则生成的 PDF 可能缺少字体或图片。
PDF 页面涉及字体、图片和平台打印实现,Windows、macOS 和 Linux 的结果可能略有差异,发布前要在目标系统实际检查。
🧾 小节总结
- PDF 导出应准备适合打印的独立页面。
printToPDF在主进程中调用。- 导出前要等待字体和图片准备完成。
- 保存文件仍然要通过系统保存对话框。
- 导出窗口完成后要及时关闭。
❓ 知识问答
Q1:为什么不直接打印当前窗口?
A:当前窗口通常包含按钮和筛选器,报告页面更容易控制内容和样式。
Q2:PDF 导出失败时应该怎么办?
A:捕获异常,给页面返回明确错误,并确保在 finally 中关闭隐藏窗口。
🧪 小练习
给报告页面增加一个表格,并在导出配置中打开背景打印:
const pdf = await reportWindow.webContents.printToPDF({
// 请在这里编写代码
});
🎉 现在你已经能把一个独立页面交付成 PDF 文件了。
