使用WebFonts时PuppeteerSharp生成PDF多语言字符显示不一致如何解决
问题根因
- 核心原因为自定义字体异步加载未完成就触发PDF生成:PuppeteerSharp默认监听页面
load或DOMContentLoaded事件就执行PDF导出,而Web字体的加载是异步行为,Azure Linux Functions环境下磁盘IO、内存资源波动会导致字体加载速度不稳定,刚好对应你遇到的三种随机输出:- 所有字体均未加载完成:仅能显示系统默认的拉丁字符,对应情况1
- 仅高棉语的Noto Sans Khmer字体未加载完成:高棉语字符无匹配字体显示空白,对应情况2
- 所有字体均加载完成:全部字符正常渲染,对应情况3
- 次要原因为Azure Linux Functions原生环境限制:系统默认预装字体极少,无兜底 fallback 字体,自定义字体加载失败时没有系统字体补全,直接显示空白/豆腐块
- 额外配置问题:当前
font-family顺序不合理,小语种字体优先级低于通用字体,可能导致字符匹配异常
修复方案
1. 强制等待字体加载完成再导出PDF
调用page.PdfAsync前,先执行代码等待所有字体加载完成,从根源避免字体未就绪的问题:
// 等待页面所有字体加载完毕 await page.EvaluateExpressionAsync("document.fonts.ready"); // 可选:额外等待100~200ms,适配低版本Chromium的渲染延迟 await page.WaitForTimeoutAsync(150);
如果使用的PuppeteerSharp版本较低不支持document.fonts.ready,可以在页面头部强制预加载所有字体资源:
<link rel="preload" href="fonts/Arial-Unicode-MS.woff2" as="font" type="font/woff2" crossorigin> <link rel="preload" href="fonts/myanmar3.woff2" as="font" type="font/woff2" crossorigin> <link rel="preload" href="fonts/noto-sans-khmer-v9-khmer-regular.woff2" as="font" type="font/woff2" crossorigin>
2. 优化字体配置
- 调整
font-family优先级,把小语种专用字体放在前面,优先匹配对应字符:$font-family: Noto-Sans-Khmer, myanmar3, Arial-Unicode-MS, sans-serif; - 把所有
@font-face的font-display属性改为block,强制字体加载完成前不显示文本,避免 fallback 字体被渲染到PDF中。
3. 适配Azure Linux Functions运行环境
启动Puppeteer时,在必要的沙箱参数外额外增加字体渲染优化参数,优先使用新版无头模式提升渲染稳定性:
var launchOptions = new LaunchOptions { Headless = true, Args = new [] { "--headless=new", "--no-sandbox", "--disable-setuid-sandbox", "--disable-dev-shm-usage", "--font-render-hinting=none", "--enable-font-antialiasing", "--disable-font-subpixel-positioning" } };
如果仍然偶现异常,可以直接把用到的字体安装到函数运行环境,彻底避免Web字体加载的不确定性,在Function启动脚本中增加以下命令即可:
mkdir -p /usr/share/fonts/truetype/custom cp ./fonts/*.woff2 /usr/share/fonts/truetype/custom/ fc-cache -f -v
4. 兜底兼容
可以适当拉长PDF生成的超时时间,同时增加2~3次失败重试逻辑,连续生成失败再返回异常。
内容的提问来源于stack exchange,提问作者DaiKeung
相关产品推荐
相关产品推荐

