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

pdf-lib填充PDF表单遇阿拉伯字符报字体类型及编码错误求助

问题排查与修复方案

核心报错根因

  • 第一个TypeError(font为NaN)的本质是异步时序错误:报错里的or n是pdf-lib源码类型校验的笔误,实际要求参数为PDFFont类型或空值。你调用embedFont方法时没有等待Promise resolve,传给updateFieldAppearances的是pending状态的Promise对象,内部类型校验时无法提取有效PDFFont实例,最终被转换为NaN触发报错。
  • WinAnsi编码报错的本质是字体绑定错误:阿拉伯字符字段默认关联PDF内置的标准Helvetica字体,该字体仅支持WinAnsi编码,无法识别阿拉伯Unicode字符;就算全局更新外观,没有单独给字段替换支持阿拉伯字符的自定义字体,依然会走旧的编码逻辑报错。

代码修正步骤

  • 调整异步逻辑顺序,把PDF加载、字体嵌入的await位置写正确,拿到真正的PDFFont实例,不要把未完成的Promise传给需要实例参数的方法。
  • 给存储阿拉伯字符的文本字段单独调用setFont方法绑定你嵌入的Cairo字体,覆盖原PDF字段关联的旧字体。
  • 所有字段赋值完成后,再调用updateFieldAppearances,传入已经嵌入完成的字体实例。

修正后可运行的代码

const { PDFDocument } = require("pdf-lib");
const path = require("path");
const fs = require("fs");
const fontkit = require("@pdf-lib/fontkit");

async function fillForm() {
  // 读取模板PDF与字体文件
  const pdfFilepath = path.join(__dirname, "/pdftemp/salary.pdf");
  const pdfTemplateBuffer = fs.readFileSync(pdfFilepath);
  const fontpath = path.join(__dirname, "/fonts/Cairo/Cairo-Regular.ttf");
  const cairoFontBuffer = fs.readFileSync(fontpath);

  // 完成PDF实例加载
  const pdfDoc = await PDFDocument.load(pdfTemplateBuffer);
  // 注册fontkit作为字体处理引擎
  pdfDoc.registerFontkit(fontkit);
  // 等待字体嵌入完成,拿到真实的PDFFont实例
  const cairoFont = await pdfDoc.embedFont(cairoFontBuffer);

  // 获取表单与所有文本字段
  const form = pdfDoc.getForm();
  const name = form.getTextField("name");
  const nationality = form.getTextField("nationality");
  const id = form.getTextField("id");
  const jobTitle = form.getTextField("jobTitle");
  const JoiningDate = form.getTextField("JoiningDate");
  const SR = form.getTextField("SR");
  const arabicName = form.getTextField("arabicName");

  // 填充英文字段
  name.setText("name name naem");
  nationality.setText("Nationality");
  id.setText("1038992853");
  jobTitle.setText("HR Officer");
  JoiningDate.setText("27/2/2021");
  SR.setText("5452");

  // 单独给阿拉伯名字段绑定支持阿拉伯字符的字体,再填充内容
  arabicName.setFont(cairoFont);
  arabicName.setText("خط عربي");

  // 传入有效的PDFFont实例更新所有字段外观
  form.updateFieldAppearances(cairoFont);

  // 保存输出PDF
  const outputPdfBytes = await pdfDoc.save();
  const outputPath = path.join(__dirname, "/pdftemp/test1.pdf");
  fs.writeFileSync(outputPath, outputPdfBytes);
}

fillForm();

补充注意事项

  • 不要用embedfont.then((i) => console.log(i))的异步回调判断字体状态:这个回调的执行时机晚于后续同步代码,控制台能打印出正常的PDFFont对象,不代表代码执行到参数校验时已经拿到了实例。
  • 如果填充的阿拉伯字符出现连写错误、顺序反向的问题,可在embedFont时补充字体特性配置,开启阿拉伯语所需的连字规则:
    const cairoFont = await pdfDoc.embedFont(cairoFontBuffer, {
      fontkit: { features: ['liga', 'rlig', 'calt'] }
    });
    
  • 阿拉伯语是从右向左书写的语言,可根据实际排版需求给阿拉伯字段设置右对齐属性,避免文字排版错乱。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.28 08:27:03