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

如何让Puppeteer加载本地图片与自定义字体?

解决Puppeteer生成图片时的本地资源加载问题

针对你遇到的本地图片无法加载和自定义字体加载的问题,我整理了具体的解决方案:

一、修复本地图片路径加载问题

当你使用page.setContent()时,页面默认的基准URL是about:blank,相对路径(比如./1.jpg)会基于这个空白页面解析,自然找不到脚本同目录的图片。有两种简单的解决方式:

方法1:设置页面的基准URL(推荐)

直接在setContent时指定baseURL为脚本所在的目录,这样HTML里的相对路径会自动解析为正确的本地文件路径:

const path = require('path');
const _ = require('lodash');
const puppeteer = require('puppeteer');

(async () => {
  const html = _.template(`
    <html>
      <body>
        <div class="testing">
          <h1>Hello {{ test }}!</h1>
          <img src="./1.jpg" alt="alt text" />
        </div>
      </body>
    </html>
  `);
  
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  
  // 设置基准URL为当前脚本所在目录
  const baseUrl = `file://${path.resolve(__dirname)}/`;
  const data = html({ test: 'World' });
  await page.setContent(data, { baseURL: baseUrl });
  
  const take = await page.$('.testing');
  await take.screenshot({ path: 'screenshot.png', omitBackground: true });
  
  await browser.close();
})();

方法2:使用绝对文件路径

把图片路径转成file://协议的绝对URL,直接替换HTML中的相对路径:

const path = require('path');
const _ = require('lodash');
const puppeteer = require('puppeteer');

(async () => {
  const html = _.template(`
    <html>
      <body>
        <div class="testing">
          <h1>Hello {{ test }}!</h1>
          <img src="{{ imageUrl }}" alt="alt text" />
        </div>
      </body>
    </html>
  `);
  
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  
  // 生成图片的绝对file URL
  const imagePath = path.resolve(__dirname, './1.jpg');
  const imageUrl = `file://${imagePath}`;
  
  const data = html({ test: 'World', imageUrl });
  await page.setContent(data);
  
  const take = await page.$('.testing');
  await take.screenshot({ path: 'screenshot.png', omitBackground: true });
  
  await browser.close();
})();

二、加载自定义字体

加载自定义字体同样需要确保字体文件的路径被正确解析,这里提供两种常用方法:

方法1:在HTML中通过@font-face引入

直接在HTML模板里添加样式,用绝对路径引入字体文件:

const path = require('path');
const _ = require('lodash');
const puppeteer = require('puppeteer');

(async () => {
  const html = _.template(`
    <html>
      <style>
        @font-face {
          font-family: 'MyCustomFont';
          src: url('{{ fontUrl }}') format('truetype');
          /* 如果是woff2等其他格式,修改format参数即可 */
        }
        .testing {
          font-family: 'MyCustomFont', sans-serif;
        }
      </style>
      <body>
        <div class="testing">
          <h1>Hello {{ test }}!</h1>
          <img src="./1.jpg" alt="alt text" />
        </div>
      </body>
    </html>
  `);
  
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  
  const baseUrl = `file://${path.resolve(__dirname)}/`;
  // 生成字体文件的绝对URL
  const fontPath = path.resolve(__dirname, './custom-font.ttf');
  const fontUrl = `file://${fontPath}`;
  
  const data = html({ test: 'World', fontUrl });
  await page.setContent(data, { baseURL: baseUrl });
  
  // 等待字体加载完成(可选但推荐,避免截图时字体未渲染)
  await page.waitForFunction(() => document.fonts.check('16px MyCustomFont'));
  
  const take = await page.$('.testing');
  await take.screenshot({ path: 'screenshot.png', omitBackground: true });
  
  await browser.close();
})();

方法2:使用page.addFontFace()方法

通过Puppeteer的API直接给页面添加字体,无需修改HTML:

const path = require('path');
const _ = require('lodash');
const puppeteer = require('puppeteer');

(async () => {
  const html = _.template(`
    <html>
      <style>
        .testing {
          font-family: 'MyCustomFont', sans-serif;
        }
      </style>
      <body>
        <div class="testing">
          <h1>Hello {{ test }}!</h1>
          <img src="./1.jpg" alt="alt text" />
        </div>
      </body>
    </html>
  `);
  
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  
  // 添加自定义字体
  const fontPath = path.resolve(__dirname, './custom-font.ttf');
  await page.addFontFace({
    family: 'MyCustomFont',
    src: `url(file://${fontPath})`,
  });
  
  const baseUrl = `file://${path.resolve(__dirname)}/`;
  const data = html({ test: 'World' });
  await page.setContent(data, { baseURL: baseUrl });
  
  await page.waitForFunction(() => document.fonts.check('16px MyCustomFont'));
  
  const take = await page.$('.testing');
  await take.screenshot({ path: 'screenshot.png', omitBackground: true });
  
  await browser.close();
})();

注意:如果字体加载较慢,建议添加page.waitForFunction()等待字体加载完成,避免截图出现默认字体的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 06:28:19