You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Puppeteer生成PDF时Firebase图片及外部字体加载失败问题

解决Puppeteer生成PDF时Firebase图片加载失败与外部字体不生效问题

问题分析

直接打开HTML时资源正常显示,但Puppeteer生成PDF时出现两个核心问题:

  • Firebase存储图片加载失败:大概率是网络等待不充分、CORS限制或Firebase资源权限配置导致
  • 外部字体不生效:主要是字体未完成加载就触发PDF生成,或headless模式下字体渲染配置缺失

分步解决方案

1. 修复Firebase图片加载问题

步骤1:先验证图片URL有效性

复制模板渲染后生成的logoImageURL和signUrl,在浏览器中直接访问:

  • 如果无法打开:检查Firebase存储规则,确保资源可公开访问(测试阶段可临时设置公开规则),或确认签名URL未过期
  • 如果能正常打开:问题出在Puppeteer的加载策略或CORS配置

步骤2:调整Puppeteer等待与CORS参数

修改浏览器启动参数和页面加载策略,确保所有资源完全加载:

const generateCertificate = async (data, traineeName, trainingPlanTitle) => {
    const browser = await puppeteer.launch({ 
        headless: 'new', // 新版headless模式更接近真实Chrome渲染逻辑
        args: [
            '--no-sandbox',
            '--disable-setuid-sandbox',
            '--disable-web-security', // 临时绕过CORS限制(生产环境需谨慎使用)
            '--allow-file-access-from-files'
        ]
    });
    const page = await browser.newPage();
    
    // 等待网络完全空闲(所有资源加载完成)
    await page.setContent(data, { waitUntil: 'networkidle0' });
    
    // 显式等待所有图片渲染可见
    await page.waitForSelector('img', { visible: true, timeout: 10000 });
    
    const pdf = await page.pdf({
        path: `${traineeName}_${trainingPlanTitle}.pdf`,
        format: 'a4',
        landscape: true,
        printBackground: true // 确保背景色、边框等样式正常渲染
    });
    await browser.close();
    return pdf;
};

步骤3:可选方案——将图片转为Base64嵌入HTML

彻底规避网络加载问题,提前把Firebase图片转为Base64后注入模板:

const fetch = require('node-fetch');

// 辅助函数:获取图片Base64编码
const getImageBase64 = async (url) => {
    const res = await fetch(url);
    const buffer = await res.buffer();
    return `data:${res.headers.get('content-type')};base64,${buffer.toString('base64')}`;
};

// 处理原始数据,替换图片URL为Base64
const prepareData = async (originalData) => {
    return {
        ...originalData,
        logoImageURL: await getImageBase64(originalData.logoImageURL),
        signUrl: await getImageBase64(originalData.signUrl)
    };
};

// 调用流程示例
const processedData = await prepareData(yourOriginalData);
const template = handlebars.compile(fs.readFileSync(path.join(__dirname, 'template.html'), 'utf8'));
const html = template(processedData);
await generateCertificate(html, traineeName, trainingPlanTitle);

2. 修复外部字体不生效问题

步骤1:更新Google Fonts链接

使用新版Google Fonts API,添加display=swap确保字体加载优先级:

<link href="https://fonts.googleapis.com/css2?family=Open+Sans&family=MonteCarlo&display=swap" rel="stylesheet">

步骤2:等待字体加载完成

在生成PDF前,显式等待字体加载完成:

// 在page.setContent后添加
await page.waitForFunction(() => {
    return document.fonts.check('16px "Open Sans"') && document.fonts.check('16px "MonteCarlo"');
}, { timeout: 5000 });

额外注意事项

  • 生产环境不要长期使用--disable-web-security,建议配置Firebase存储的CORS规则,允许Puppeteer所在服务器访问
  • 确保Puppeteer版本为最新,旧版本headless模式可能存在渲染bug
  • 如果是Windows系统,可能需要额外配置字体支持,可尝试安装缺失字体或添加--font-render-hinting=none启动参数

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 08:20:32