柜面连打三张凭证、仓库一次打五张面单、窗口批量补打历史单据------单张 printHtml 循环调用看似简单,实则容易踩 并发、顺序、预览混用 等坑。
本文以 npm 包 web-print-pdf 的 batchPrint 为核心,说明批量静默打印的正确用法、合并规则与常见错误;终端需安装并运行 Web打印专家 本地客户端。
| 资源 | 链接 |
|---|---|
| 官网 | http://webprintpdf.com/ |
| 客户端下载 | http://webprintpdf.com/downloadApp/ |
| npm 包 | https://www.npmjs.com/package/web-print-pdf |
| GitHub | https://github.com/weixiaoyi/web-print-pdf |
1. 为什么不要自己 for 循环调 printHtml
手写循环的问题:
| 自己循环 | batchPrint |
|---|---|
| N 次 WebSocket 往返,延迟叠加 | 一次请求,服务端编排 |
| 难以保证 PDF 全部生成后再统一出纸 | 先并行转 PDF,再按任务打印 |
| 预览 / 打印 action 容易混在一批里 | 服务端强制校验 action 一致 |
| 前端要自己处理部分失败 | 统一错误返回,日志在客户端 |
结论 :批量场景应优先 batchPrint,而不是 for + printHtml。
2. batchPrint 在架构里的位置
业务页 batchPrint(printTaskList, ...)
│ WebSocket 一条消息 type: batchPrint
▼
Web打印专家
├─ 并行:各 task → HTML/PDF 生成(generatePdf 队列)
└─ 串行/并发:各 PDF → 打印子进程(printPdf 队列)
▼
本地打印机(Windows Spooler / CUPS)
客户端内部对 PDF 生成 与 打印下发 各有一套 TaskQueue,根据 CPU / 内存动态控制并发,避免连点「批量打印」把机器打满。
3. 快速上手
3.1 最小示例:连打两张 HTML
javascript
import webPrintPdf from "web-print-pdf";
const pdfOptions = {
paperFormat: "A4",
margin: { top: "10px", bottom: "10px", left: "10px", right: "10px" },
printBackground: true,
};
const printOptions = {
printerName: "你的打印机名", // 建议 getPrinterList() 动态获取
paperFormat: "A4",
copies: 1,
};
const extraOptions = { action: "print" };
await webPrintPdf.batchPrint(
[
{ data: "<div><h1>凭证一</h1></div>", type: "printHtml" },
{ data: "<div><h1>凭证二</h1></div>", type: "printHtml" },
],
pdfOptions,
printOptions,
extraOptions
);
3.2 混合类型:HTML + 远程 PDF
javascript
await webPrintPdf.batchPrint(
[
{ data: "<div>小票 HTML</div>", type: "printHtml" },
{ data: "https://intranet/reports/1001.pdf", type: "printPdfByUrl" },
{ data: "https://intranet/label.png", type: "printImageByUrl" },
],
pdfOptions,
printOptions,
extraOptions
);
3.3 支持的 task.type
| type | data 含义 |
|---|---|
printHtml |
HTML 字符串 |
printHtmlByUrl |
可访问的报表 URL |
printHtmlByBase64 |
Base64 编码的 HTML |
printPdfByUrl |
PDF 文件 URL |
printPdfByBase64 |
Base64 PDF |
printImageByUrl |
图片 URL |
printImageByBase64 |
Base64 图片 |
4. 参数合并规则(必看)
调用签名:
javascript
batchPrint(printTaskList, pdfOptions, printOptions, extraOptions)
浅合并 :全局的 pdfOptions / printOptions / extraOptions 会与每个 task 上的同名字段合并,task 级优先。
javascript
await webPrintPdf.batchPrint(
[
{
data: "<div>A</div>",
type: "printHtml",
printOptions: { copies: 2 }, // 覆盖全局 copies
},
{
data: "<div>B</div>",
type: "printHtml",
printOptions: { printerName: "二楼打印机" }, // 单独指定打印机
},
],
{ paperFormat: "A4", printBackground: true }, // 全局 pdfOptions
{ paperFormat: "A4", copies: 1 }, // 全局 printOptions
{ action: "print", requestTimeout: 30 }
);
4.1 硬约束:action 必须一致
合并后,所有 task 的 extraOptions.action 必须相同 (要么全是 print,要么全是 preview)。若一批里既有静默又有预览,服务端直接抛错:
text
every printTask's extraOptions.action must be equal in printTaskList when after shallow merged!
排坑 :全局 extraOptions.action = 'print',某个 task 误设 action: 'preview' → 整批失败。
4.2 预览模式
全局或 task 设 action: 'preview' 时,不会出纸 ,返回 printPreviewUrl 与 pdfs 列表,供联调版式。
5. 业务场景配方
5.1 柜面连打「受理单 + 回执 + 清单」
javascript
const tasks = [
{ data: receiptHtml, type: "printHtml" },
{ data: ackHtml, type: "printHtml" },
{ data: listHtml, type: "printHtml" },
];
await webPrintPdf.batchPrint(tasks, pdfOptions, printOptions, { action: "print" });
三份 HTML 建议各自内联样式,减少对外部 CSS 依赖。
5.2 不同打印机(task 级 printOptions)
javascript
await webPrintPdf.batchPrint(
[
{ data: customerCopy, type: "printHtml", printOptions: { printerName: "前台激光" } },
{ data: archiveCopy, type: "printHtml", printOptions: { printerName: "办公室 A4" } },
],
pdfOptions,
{},
extraOptions
);
5.3 内网 URL 批量(带登录态)
全局 extraOptions 传 cookie / header:
javascript
const extraOptions = {
action: "print",
requestTimeout: 30,
cookies: { SESSION: "xxx" },
httpHeaders: { Authorization: "Bearer token" },
};
await webPrintPdf.batchPrint(
urls.map((url) => ({ data: url, type: "printHtmlByUrl" })),
pdfOptions,
printOptions,
extraOptions
);
6. 排坑清单
| 现象 | 常见原因 | 处理 |
|---|---|---|
| 整批报错 action 不一致 | task 与全局 action 混用 | 统一为 print 或 preview |
| 只打了第一张 | 前端循环误用 await 顺序 / 客户端未启动 | 改用 batchPrint;确认 Web打印专家在运行 |
| 后面几张空白 | HTML 无 @media print / 字体缺失 |
内联样式;安装字体 |
| 队列堆积不出纸 | 打印机卡纸、驱动异常 | 见《故障排查手册》08 篇 |
| 批量很慢 | 单 task 的 URL 超时;PDF 队列满 | 调 requestTimeout;减少单次 batch 数量 |
| printerName 报错 | 硬编码开发机名称 | getPrinterList() 动态取 |
6.1 批量大小建议
- 单次 5~20 张 较稳妥(视 HTML 复杂度与机器配置)
- 超大 batch 建议业务侧拆批,并在 UI 上显示「打印队列处理中」
- 客户端可通过日志 API 查看 PDF / 打印阶段耗时
6.2 不要用 batchPrint 冒充「严格顺序保证」
PDF 生成阶段是 Promise.all 并行 ;打印阶段也是并行触发多个 printPdf.print。若业务要求 严格先 A 后 B 的物理顺序,应在应用层拆成两次调用,或与运维确认打印机队列 FIFO 行为。
7. 与单张 API 的选型
| 场景 | 推荐 API |
|---|---|
| 单张凭证 | printHtml |
| 单张远程 PDF | printPdfByUrl |
| 连打多张 / 混合类型 | batchPrint |
| 服务端推任务 | 远程打印 / _printByRawMessage |
8. 小结
- 批量静默打印 请用
batchPrint,不要手写 for 循环。 - 搞清 浅合并 与 action 一致 两条规则,能避开大部分联调失败。
- 终端安装 Web打印专家,前端
npm install web-print-pdf即可。
更多 API 与参数说明见 npm 文档与客户端内置「运行示例」。