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

如何在@react-pdf/pdfkit中添加使用自定义字体并解决browser build报错

解决@react-pdf/pdfkit浏览器环境自定义字体报错问题

报错原因

fontkit.openSync unavailable for browser build 报错的根本原因是:@react-pdf/pdfkit 的浏览器构建版本移除了 Node 环境专属的同步文件读取API,你直接传入本地文件路径字符串的注册方式只适用于 Node 服务端场景,浏览器环境无法直接读取本地文件系统路径,需要先将字体文件加载为二进制数据再注册。


解决步骤

1. 调整字体存储位置

将所有 .ttf 字体文件存放在项目的 public/fonts 目录下,保证浏览器可以通过公共路径直接请求到字体资源。

2. 新增字体预加载工具函数

// 加载字体为ArrayBuffer格式
const loadFontBuffer = async (fontFileName) => {
  const res = await fetch(`/fonts/${fontFileName}`);
  return await res.arrayBuffer();
};

3. 修正原有生成PDF的逻辑

修正两个核心问题:一是用Promise.all等待所有字体加载注册完成再渲染内容,二是注册字体时传入二进制数据而非路径。

import utils from "./utils";
const SVGtoPDF = require("svg-to-pdfkit");
const PDFDocument = require("@react-pdf/pdfkit").default;
const { Base64Encode } = require("base64-stream");

const generatePDF = async (width, height, canvas, fonts) => {
  const canvasSvg = canvas.toSVG();
  return await new Promise(async (resolve, reject) => {
    try {
      const doc = new PDFDocument({
        bufferPages: true,
        size: [width * 0.75, height * 0.75],
      });

      // 等待所有字体加载并注册完成
      const fontConfigList = utils.getFont(fonts);
      await Promise.all(fontConfigList.map(async (font) => {
        // 提取字体文件名
        const fontFileName = font.path.split("/").pop();
        const fontBuffer = await loadFontBuffer(fontFileName);
        doc.registerFont(font.family, fontBuffer);
      }));
      
      // 注册完成后再调用字体渲染文本
      doc.font("Pacifico").text("Hello Message");
      
      let finalString = "";
      const stream = doc.pipe(new Base64Encode());
      SVGtoPDF(doc, canvasSvg, 0, 0);
      stream.on("data", (chunk) => (finalString += chunk));
      stream.on("end", () => {
        resolve(finalString);
      });
      doc.end();
    } catch (err) {
      reject(err);
    }
  });
};

export default generatePDF;

可选优化方案

如果字体文件体积较小,可以提前将 .ttf 文件转为 Base64 字符串,直接将 Base64 传入 registerFont 即可,不需要额外的异步加载逻辑:

// Pacifico字体的Base64字符串,注意前面要加data:font/ttf;base64,前缀
const PACIFICO_FONT_BASE64 = "data:font/ttf;base64,xxxxxx......";
doc.registerFont("Pacifico", PACIFICO_FONT_BASE64);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 15:15:03