You need to enable JavaScript to run this app. 如何在AWS Serverless Node.js Lambda中为Puppeteer PDF页眉页脚加Google字体
优惠活动
大模型
产品
解决方案
定价
更多

如何在AWS Serverless Node.js Lambda中为Puppeteer PDF页眉页脚加Google字体

AWS Lambda + Puppeteer PDF 自定义字体生效方案

问题背景

  • 服务环境:基于Serverless框架部署的Node.js AWS Lambda,现有Puppeteer生成PDF的核心流程可正常运行
  • 待实现需求:在生成PDF的页眉、页脚区域应用自定义字体
  • 已尝试的无效方案:
    • 通过Serverless Layer挂载Google字体包到Lambda运行环境
    • 在主页面CSS中通过@font-face导入自定义字体
  • 核心问题:如何让自定义字体在PDF的页眉、页脚区域正常渲染

失效根因

Puppeteer生成PDF时,页眉、页脚的渲染逻辑运行在完全独立的沙箱上下文中,和主页面的DOM渲染环境互相隔离。主页面内加载的CSS字体、系统环境中挂载的全局字体,都不会被页眉页脚的渲染上下文识别,这是两种尝试方案全部失效的核心原因。

可直接复用的实现步骤

  1. 绕开外部文件路径依赖,将字体转为base64内嵌
    不管是下载的Google字体还是本地自定义字体文件,直接在代码运行阶段读取为base64字符串,生成标准的@font-face CSS规则,从根本上避免Lambda环境下文件路径找不到、系统字体加载不生效的问题:
    import * as path from "path";
    import * as fs from "fs";
    // 模块加载阶段一次性读取字体,避免重复IO开销
    const CUSTOM_FONT_BASE64 = fs.readFileSync(
      path.join(__dirname, "./assets/fonts/你的自定义字体.ttf")
    ).toString("base64");
    const EMBEDDED_FONT_CSS = `
      @font-face {
        font-family: 'PDFCustomFont';
        src: url(data:font/ttf;base64,${CUSTOM_FONT_BASE64}) format('truetype');
        font-weight: normal;
        font-style: normal;
      }
    `
    
  2. 修正现有PDF生成逻辑的加载时序问题
    原代码中waitForNavigation和setContent自带的等待逻辑存在时序重复,容易导致字体未完成加载就启动PDF渲染。调整后的核心逻辑:
    static getPDFBuffer: GetPDFBuffer = async (html: string, options: any) => {
      let browser = null;
      try {
        const executablePath = process.env.IS_OFFLINE
          ? null
          : await chromium.executablePath;
        browser = await chromium.puppeteer.launch({
          args: chromium.args,
          executablePath,
        });
        const page = await browser.newPage();
        // 先将内嵌字体样式注入主页面上下文,触发字体预加载
        await page.addStyleTag({ content: EMBEDDED_FONT_CSS });
        // 加载页面内容,等待所有资源、字体加载完成
        await page.setContent(html, { 
          waitUntil: ['load', 'domcontentloaded', 'networkidle0', 'fontsready'] 
        });
        // 注入PDF生成配置,将字体样式内嵌到页眉页脚模板中
        const finalPdfOptions = {
          ...options,
          displayHeaderFooter: true,
          // 页眉模板:直接内嵌字体CSS,指定文字字体
          headerTemplate: `
            <style>${EMBEDDED_FONT_CSS}</style>
            <div style="font-family: 'PDFCustomFont', sans-serif; font-size: 12px; width: 100%; text-align: center; padding: 0 20px;">
              你的自定义页眉内容
            </div>
          `,
          // 页脚模板:同上
          footerTemplate: `
            <style>${EMBEDDED_FONT_CSS}</style>
            <div style="font-family: 'PDFCustomFont', sans-serif; font-size: 10px; width: 100%; text-align: center; padding: 0 20px;">
              你的自定义页脚内容
            </div>
          `
        }
        return await page.pdf(finalPdfOptions);
      } catch (error) {
        return error;
      } finally {
        if (browser !== null) {
          await browser.close();
        }
      }
    };
    
  3. Lambda环境适配注意点
    • 不要将字体文件仅放在Serverless Layer中,直接将字体文件打包进函数代码包,通过上述base64方式读取,可靠性远高于依赖Layer挂载的系统字体
    • 不要在页眉、页脚模板中引用外部CDN的字体链接,无服务器环境下可能因网络权限问题导致加载失败
    • 字体文件建议选择woff/ttf格式,避免用体积过大的otf格式,减少Lambda冷启动的加载耗时

内容的提问来源于stack exchange,提问作者Abid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.06 06:54:06