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
相关产品推荐
相关产品推荐

