i_print_electron
v0.1.4
Published
Stateless HTML-to-PDF-to-PDFium silent printing for Windows Electron applications.
Readme
i_print_electron
面向 Windows x64 Electron 应用的无状态静默打印 npm 包。每个任务由 renderer 下发完整打印参数,主进程依次执行:
HTML → Electron PDF → 内置 PDFium BGRA → BMP → Electron silent print
不启动 HTTP/WebSocket 服务,不下载运行时资源,不依赖系统 PDF 阅读器,也不持久化打印配置。
插件用于把 Electron renderer 中的 HTML 打印任务交给主进程,在不弹出系统打印对话框的情况下完成 PDF 生成、PDFium 栅格化和指定 Windows 打印机提交。它适合标签、工单等纸张尺寸和打印参数需要由业务端逐次明确下发的场景;submitted 只表示驱动接受了任务,不代表纸张已经物理输出。
当前验证状态
Electron 17.4.11 至 44.1.0 的 28 个逐主版本精确补丁已完成 Windows x64 自动化矩阵:A4、60×80mm 单页/多页 HTML → PDF、PDFium → BMP、每版连续 100 次生成与渲染、真实 IPrint SDK/Preload/IPC、打印机枚举、validatePrintConfig(),以及从 npm .tgz 安装后的 ASAR/extraResources 打包运行均通过。
尚未指定生产打印机和驱动,因此没有向任意设备擅自提交任务,也没有执行每型号 100 张真实纸张测试。矩阵结论目前统一为 conditional,不能视为最终生产支持范围。
详见 Electron 支持矩阵 和 逐版本测试报告。
Electron 兼容性列表
以下版本均已完成开发模式、每版 100 次 PDF/PDFium/BMP 稳定性、真实 IPrint 示例以及 ASAR 安装目录测试。因实体打印机 100 张测试尚待现场执行,当前结论均为条件兼容,不等同于最终生产支持声明。
| Electron | 自动化测试 | 实体静默打印 | 当前结论 |
|---|---|---|---|
| 17.4.11 | 通过 | 待现场 | conditional |
| 18.3.15 | 通过 | 待现场 | conditional |
| 19.1.9 | 通过 | 待现场 | conditional |
| 20.3.12 | 通过 | 待现场 | conditional |
| 21.4.4 | 通过 | 待现场 | conditional |
| 22.3.27 | 通过 | 待现场 | conditional |
| 23.3.13 | 通过 | 待现场 | conditional |
| 24.8.8 | 通过 | 待现场 | conditional |
| 25.9.8 | 通过 | 待现场 | conditional |
| 26.6.10 | 通过 | 待现场 | conditional |
| 27.3.11 | 通过 | 待现场 | conditional |
| 28.3.3 | 通过 | 待现场 | conditional |
| 29.4.6 | 通过 | 待现场 | conditional |
| 30.5.1 | 通过 | 待现场 | conditional |
| 31.7.7 | 通过 | 待现场 | conditional |
| 32.3.3 | 通过 | 待现场 | conditional |
| 33.4.11 | 通过 | 待现场 | conditional |
| 34.5.8 | 通过 | 待现场 | conditional |
| 35.7.5 | 通过 | 待现场 | conditional |
| 36.9.5 | 通过 | 待现场 | conditional |
| 37.10.3 | 通过 | 待现场 | conditional |
| 38.8.6 | 通过 | 待现场 | conditional |
| 39.8.10 | 通过 | 待现场 | conditional |
| 40.10.6 | 通过 | 待现场 | conditional |
| 41.10.7 | 通过 | 待现场 | conditional |
| 42.11.0 | 通过 | 待现场 | conditional |
| 43.5.0 | 通过 | 待现场 | conditional |
| 44.1.0 | 通过 | 待现场 | conditional |
测试共覆盖 28 个 Electron 精确版本、2,800 次连续生成与渲染、36 项 Vitest、npm .tgz 独立消费、Koffi/PDFium 的开发与打包路径、A4 和 60×80mm 横向/纵向及单页/多页、ERP WindingPrintContent 静态 HTML 夹具、中文/英文/表格/CSS 背景/data URL 图片、页数与物理尺寸、临时文件清理、Microsoft Print to PDF 直接保存、真实 IPrint 的 validatePrintConfig()/print() 调用链。逐版本环境、命令、日志和产物路径见完整测试报告。
安装
发布包:
npm install i_print_electron本地联调:
npm install file:D:/study-project/i_print_electronelectron 是 peer dependency;koffi 是运行时依赖。当前 peer dependency 暂时固定为开发基线 17.4.11;待生产打印机现场验收后,再按连续通过区间扩大范围。
主进程
import { app } from 'electron';
import { registerIPrintElectron } from 'i_print_electron/main';
let registration: ReturnType<typeof registerIPrintElectron>;
app.whenReady().then(() => {
registration = registerIPrintElectron({
// 默认即为 10 分钟;可配置为 0–10080 分钟,0 表示打印结束后立即删除。
pdfRetentionMinutes: 10,
// 可选。默认:<current project>/temp/i_print_electron
// tempDirectory: 'D:/your-project/temp/i_print_electron',
});
});
app.on('before-quit', () => {
void registration?.dispose();
});主进程只注册一组固定 IPC channel,所有打印任务通过一个 FIFO 串行队列执行;相同 requestId 在进程生命周期内不会重复提交。
PDF 临时文件
成功生成的 PDF 默认保留 10 分钟,路径固定为:
<当前项目>/temp/i_print_electron/<requestId>-<随机后缀>/output.pdf“当前项目”由主进程启动时的 process.cwd() 确定。source.html、打印 HTML 和 BMP 页面在任务结束后立即删除,仅保留 output.pdf;到期后整个任务目录自动删除。应用异常退出时可能来不及执行定时器,下一次注册插件时会自动清理超过保留时间的旧目录。
如消费方需要明确指定位置,可传入绝对路径:
registerIPrintElectron({
tempDirectory: 'D:/jh/erp-pad/temp/i_print_electron',
pdfRetentionMinutes: 30,
});该目录属于主进程内部诊断存储,不通过 Preload 向 renderer 暴露任意文件访问能力。
Preload
import { contextBridge, ipcRenderer } from 'electron';
import { createIPrintElectronApi } from 'i_print_electron/preload';
contextBridge.exposeInMainWorld(
'iPrintElectron',
createIPrintElectronApi(ipcRenderer),
);必须保持:
webPreferences: {
contextIsolation: true,
nodeIntegration: false,
}Renderer 与 IPrint
import IPrint from 'D:/study-project/i_print_pro/public/sdk/IPrint';
import { IPrintElectronSdkAdapter } from 'i_print_electron/renderer';
const clientOptions = new IPrintElectronSdkAdapter().createClientOptions();
<IPrint
clientOptions={clientOptions}
printContent={printContent}
previewContent={printContent}
previewTask={false}
printer={printerName}
paperSize="60*80"
storeKey="winding-print"
/>完整测试示例位于 examples/i-print-react,它直接编译并运行 D:/study-project/i_print_pro/public/sdk/IPrint,没有用 mock 或底层 printHtml() 直调替代。
首个消费方 D:/jh/erp-pad 采用双模式接入:Web 环境保持原 react-to-print;Electron 环境打印前弹窗选择“原打印模式”或“IPrint 静默打印”。IPrint 模式的目标设备由 ERP 环境变量 VITE_WINDING_PRINTER_NAME 提供。
也可以直接使用 Preload API:
const receipt = await window.iPrintElectron!.printHtml({
requestId: crypto.randomUUID(),
name: 'winding-labels',
html,
printerName,
copies: 1,
colorMode: 'monochrome',
duplexMode: 'simplex',
collate: false,
layout: {
paperName: '60x80mm',
paperWidthMm: 60,
paperHeightMm: 80,
landscape: false,
marginTopMm: 0,
marginRightMm: 0,
marginBottomMm: 0,
marginLeftMm: 0,
scalingMode: 'ActualSize',
renderDpi: 300,
borderless: false,
printBackground: true,
},
});
console.log(receipt.status); // submittedsubmitted 只表示 Electron 回调确认任务已接受,不表示纸张已物理输出。
Electron Builder
PDFium 必须作为固定安装资源复制,Koffi 必须从 ASAR 解包:
{
"extraResources": [
{
"from": "node_modules/i_print_electron/resources/win32-x64",
"to": "i_print_electron/win32-x64",
"filter": ["pdfium.dll", "LICENSE.pdfium.txt", "pdfium.sha256"]
}
],
"asarUnpack": [
"node_modules/koffi/**",
"node_modules/@koromix/koffi-win32-x64/**"
]
}生产运行时只从 <process.resourcesPath>/i_print_electron/win32-x64 加载 PDFium。
构建与测试
yarn typecheck
yarn test
yarn verify:resources
yarn build
yarn typecheck:example
yarn build:example
yarn test:electron:smoke
yarn test:electron:matrix
yarn test:electron:compat
yarn test:example:smoke
yarn test:example:matrix
yarn test:electron:packaged
yarn test:package-consumer
yarn pack:check测试证据按 Electron 精确版本存放在 test-results/electron-<version>/。
已知边界
- 仅实现 Windows x64。
preview: true和skipPrinting: true在 Electron SDK 适配入口明确返回UNSUPPORTED_OPERATION。- Electron 无法返回 Windows JobId,也不能确认缺纸、卡纸或物理打印完成。
- 驱动可能忽略 DPI、双面、配页、自定义纸张或无边距参数。
- Electron 21 起
printToPDF()自定义纸张采用 CDP 英寸语义;包内已按 Electron 20/21 边界兼容并有回归测试。 - 真实打印机型号、驱动、silent 提交和每型号 100 张稳定性仍需现场验收。
