Chrome打印PDF错乱主因是@media print未适配、字体未嵌入或Web字体加载失败;puppeteer空白页因等待策略不当;文字不可选源于光栅化;中文文件名乱码系Content-Disposition编码不兼容。
Chrome 浏览器直接打印为 PDF 时字体/布局错乱
网页转 pdf 最常用也最靠谱的方式,就是用 chrome 的「另存为 pdf」功能(ctrl+p → 选择「另存为 pdf」)。但很多人发现导出后中文乱码、按钮消失、表格挤成一团——根本不是“所见即所得”。
问题核心在于:@media print 样式没适配,或用了 display: none / visibility: hidden 的打印隐藏逻辑,又或者字体未嵌入、Web 字体加载失败。
- 检查页面是否在
@media print中把关键元素设为display: none,比如侧边栏、广告位;临时注释掉它们再试 - 确保中文字体使用系统已有字体(如
"PingFang SC", "Microsoft YaHei", sans-serif),避免依赖未加载的@font-face - 给容器加
size: A4;和margin: 0;(在@media print下),否则 Chrome 默认按屏幕尺寸缩放,导致内容被裁切 - 若含 SVG 或 Canvas,需确认其渲染已完成(PDF 导出不执行 JS 动画或异步绘制)
用 puppeteer 服务端生成 PDF 时空白页或超时
puppeteer 是 Node.js 环境下稳定生成 PDF 的首选,但它默认等待 networkidle0,而页面里若有轮询请求、埋点脚本、未 resolve 的 Promise,就会卡住甚至超时返回空页。
- 改用
waitUntil: 'domcontentloaded'或'networkidle2',避免等死循环请求 - 显式设置
timeout: 30000,并捕获TimeoutError,防止进程僵死 - 禁用图片加载可提速:
await page.setRequestInterception(true); page.on('request', req => req.url().match(/\.(jpg|jpeg|png|gif)$/i) ? req.abort() : req.continue()); - PDF 生成前调用
await page.addStyleTag({ content: '@page { size: A4; margin: 0.5in; }' });,比靠 CSS 更可靠
PDF 导出后文字不可选、搜索不到
这是 rasterization(光栅化)导致的典型问题:Chrome 把整个页面当一张图渲染了。常见于启用了 --disable-gpu、--no-sandbox 或强制 pdfPreferences: { printBackground: true } 却没配对 CSS 的场景。
- 确保 HTML 元素是真实文本节点,而非用
canvas或background-image模拟的文字 - 不要在
@media print中对body或html设transform: scale(),这会让 Chrome 回退到位图模式 - 用
pdfOptions = { format: 'A4', printBackground: true, preferCSSPageSize: true },其中preferCSSPageSize是关键开关,它让 Puppeteer 尊重 CSS 中的@page设置,维持文本层 - 如果必须用背景图,单独导出文字层 PDF + 图片层 PNG,后期用
pdf-lib合并
中文标题带书名号、破折号时 PDF 文件名乱码
浏览器下载 PDF 时,Content-Disposition 头里的 filename= 值若含中文或特殊符号,不同浏览器解析规则不一。Chrome 支持 UTF-8 编码(filename*=UTF-8''xxx.pdf),Safari 却只认 filename 的 ASCII 子集。
立即学习“前端免费学习笔记(深入)”;
- 服务端生成时,用
encodeURIComponent对文件名做编码,再拼进filename*=UTF-8''...;同时保留一个纯英文 fallback:filename="report.pdf" - 前端触发下载时,别用
download属性直接写中文名(<a download="我的报告.pdf"></a>),改用Blob + URL.createObjectURL+a.click(),并在创建 Blob 时指定type: 'application/pdf' - 测试时用 Safari 打开确认:若文件名变成
unknown.pdf,说明filename*未生效或编码错误
真正难的不是生成 PDF,而是让每台机器、每个浏览器、每次点击都输出一致的可读、可搜、可复制的 PDF。字体链、媒体查询、异步资源、HTTP 头细节——漏掉任意一环,用户看到的就是白纸、黑块或乱码字。











