wkhtmltopdf 是最稳的本地 pdf 生成方案,支持 css 打印规则、分页和中文;需解决无显示报错、字体乱码、路径问题;puppeteer 更灵活但资源消耗大;jspdf+html2canvas 适合简单前端导出。

用 wkhtmltopdf 命令行直接转,最稳
本地生成 PDF 且要保留样式、分页、中文,wkhtmltopdf 是目前兼容性最好、可控性最强的选择。它本质是把 WebKit 渲染引擎封装成命令行工具,不是简单截图或 DOM 快照,所以能处理 CSS @media print、page-break-before 这类规则。
常见错误现象:wkhtmltopdf 报 QXcbConnection: Could not connect to display(Linux 无图形环境时)、中文字体乱码、页面截断在第一屏。
- Linux 服务器上必须加
--no-xserver或装 headless 依赖(如xvfb-run) - 中文字体失效?把字体文件路径显式传给
--font-family,或确保系统已安装并被 Fontconfig 识别(fc-list :lang=zh可查) - HTML 里用了相对路径的 CSS/JS?转 PDF 前先用绝对路径重写,或用
--enable-local-file-access(但有安全风险,仅限可信 HTML) - 默认 A4 尺寸下内容被压缩?加
--zoom 1.2或改--page-width/--page-height
示例:wkhtmltopdf --margin-top 20 --margin-bottom 20 --page-size A4 --encoding utf-8 index.html output.pdf
前端用 jsPDF + html2canvas 在浏览器里转,适合简单页面
如果用户点击按钮就在当前页面生成 PDF,不走后端,那只能靠前端 JS。但得认清限制:html2canvas 是截图逻辑,无法真正理解 CSS 分页、打印媒体查询,也不支持跨域资源、iframe 内容、SVG 滤镜等。
立即学习“前端免费学习笔记(深入)”;
使用场景:内部管理页导出简报、表单结果页、不含复杂布局的静态报告。
-
html2canvas对transform、filter、position: fixed支持差,建议提前用getComputedStyle检查渲染一致性 -
jsPDF的addImage接收 base64 图片,但大图易触发内存溢出;建议限制截图区域高度,分页拼接 - 中文乱码?
jsPDF默认不嵌入中文字体,必须手动加载 TTF 并addFont,否则显示方块 - 不要对整个
document.body截图——滚动条位置、固定定位元素会错位,应指定一个干净的<div id="pdf-root"> <p>示例关键调用:<code>html2canvas(document.getElementById('pdf-root')).then(canvas => { const img = canvas.toDataURL('image/png'); const pdf = new jsPDF(); pdf.addImage(img, 'PNG', 0, 0); pdf.save('report.pdf'); });Node.js 后端用
puppeteer渲染再保存,灵活性最高如果你有 Node 服务,又需要精确控制渲染时机(比如等图表加载完、等动画结束、注入自定义脚本),
puppeteer是比wkhtmltopdf更现代的选择。它操控真实 Chromium 实例,支持 await、拦截请求、模拟设备、甚至 PDF 加密。性能影响:每次生成都启一个 Chromium 进程,高并发下内存吃紧;建议复用 browser 实例,别每次都
puppeteer.launch()。- PDF 空白?多半是没等 HTML 完全加载,用
page.waitForSelector('.content-loaded')或page.evaluate(() => document.fonts.ready) - 字体还是糊?不是加
--font-family,而是让 Puppeteer 加载字体文件:await page.addStyleTag({ content: '@font-face { font-family: "SimSun"; src: url("/fonts/simsun.ttc"); }' }) - 生成的 PDF 没有页眉页脚?
page.pdf()的displayHeaderFooter: true需配合headerTemplate/footerTemplate,且模板里只支持有限 CSS(不能用外部样式表) - Windows 下报
Failed to launch chrome?确认是否安装了 Chromium 二进制,或设executablePath指向已有的 Chrome
示例参数:
await page.pdf({ format: 'A4', printBackground: true, margin: { top: '20px' }, path: 'out.pdf' });别踩这些坑:路径、编码、字体、跨域
几乎所有 HTML 转 PDF 失败,根源就这四点。不是工具不行,是环境没对齐。
- HTML 里的
<link rel="stylesheet" href="css/main.css">—— 如果没开本地文件访问或没配好 base URL,CSS 就是 404,样式全丢 - HTML 声明了
<meta charset="gb2312">锛
- PDF 空白?多半是没等 HTML 完全加载,用











