同一份 PDF 在不同机器上打开,样子可能并不一致:文档引用的字体本机没有,阅读器就临时拿别的字体顶上;反过来,品牌规范或法务要求外发文件只保留指定字体,也得先知道原文用了哪些字体。浏览器里的常规 PDF 库主要把页面画出来,字体资源这一层并不对外开放。
本文用 Spire.PDF for JavaScript 读取和替换 PDF 中的字体:先通过 PdfDocument.UsedFonts 列出文档用到的字体,再用 PdfUsedFont.Replace() 把标准字体与未嵌入的 TrueType 字体换成新的 TrueType 字体。整个处理在浏览器端完成,文件通过虚拟文件系统(VFS)读写,不需要上传到服务器。
本文介绍两个核心功能点:
有关安装和项目配置,请参考 React 项目中集成 Spire.PDF for JavaScript。下面的示例假定 Spire.PDF 已安装、WebAssembly 模块已初始化。
获取 PDF 中使用的字体
Spire.PDF for JavaScript 提供 PdfDocument.UsedFonts 属性,用于读取文档中用到的全部字体。集合里每一项都是 PdfUsedFont,Name、Size、Style、Type 分别给出字体名、字号、字形与字体类型。
具体操作步骤如下:
- 获取 Spire.PDF 的 WASM 模块,确认已就绪。
- 将示例 PDF 载入 VFS,创建
PdfDocument对象并加载该文件。 - 读取
PdfDocument.UsedFonts,逐个取出集合中的PdfUsedFont。 - 汇总每个字体的名称、字号、样式与类型,写入文本文件。
- 从 VFS 读出结果文件并触发浏览器下载。
获取 PDF 中字体的代码如下:
function App() {
const getFonts = async () => {
// 获取 Spire.PDF WASM 模块
const pdfModule = window.wasmModule?.spirepdf;
// 检查模块是否就绪
if (!pdfModule) {
alert('Spire.PDF is not ready yet');
return;
}
// 将示例 PDF 载入 VFS
const inputFileName = 'Font_Sample.pdf';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/data/`);
// 创建 PdfDocument 对象并加载文档
const doc = new pdfModule.PdfDocument();
doc.LoadFromFile(inputFileName);
// UsedFonts 列出文档当前用到的字体
const fonts = doc.UsedFonts;
const styleNames = new Map([
[pdfModule.PdfFontStyle.Regular.value, 'Regular'],
[pdfModule.PdfFontStyle.Bold.value, 'Bold'],
[pdfModule.PdfFontStyle.Italic.value, 'Italic'],
[pdfModule.PdfFontStyle.Underline.value, 'Underline'],
[pdfModule.PdfFontStyle.Strikeout.value, 'Strikeout'],
]);
const typeNames = new Map([
[pdfModule.PdfFontType.Standard.value, 'Standard'],
[pdfModule.PdfFontType.TrueType.value, 'TrueType'],
[pdfModule.PdfFontType.TrueTypeEmbedded.value, 'Embedded TrueType'],
]);
// 逐个汇总字体的名称、字号、样式与类型
let report = `Document: ${inputFileName}\r\nFont count: ${fonts.length}\r\n\r\n`;
for (let i = 0; i < fonts.length; i++) {
const font = fonts.get(i);
report += `${i + 1}. ${font.Name}\r\n`;
report += ` Size: ${font.Size}\r\n`;
report += ` Style: ${styleNames.get(font.Style.value)}\r\n`;
report += ` Type: ${typeNames.get(font.Type.value)}\r\n\r\n`;
}
// 字体清单写入 VFS
const outputFileName = 'FontList.txt';
window.dotnetRuntime.Module.FS.writeFile(outputFileName, report);
doc.Close();
// 从 VFS 读取结果文件,触发下载
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'text/plain;charset=utf-8' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Get the Fonts Used in a PDF</h1>
<button onClick={getFonts}>
Get fonts
</button>
</div>
);
}
export default App;
字体清单写入文本文件,列出字体名称、字号、样式与类型:

替换 PDF 中使用的字体
Spire.PDF for JavaScript 还提供 PdfUsedFont.Replace() 方法,把文档里的一种字体换成另一个字体对象。它只支持标准 Type1 字体和未嵌入的 TrueType 字体;内嵌字体(例如子集嵌入的中日文字体)无法替换,遍历时需要跳过。
具体操作步骤如下:
- 获取 Spire.PDF 的 WASM 模块,确认已就绪。
- 将示例 PDF 与替换用的字体文件载入 VFS,字体文件放到
/Library/Fonts/。 - 创建
PdfDocument对象加载 PDF,读取PdfDocument.UsedFonts。 - 创建
PdfTrueTypeFont对象,遍历UsedFonts,跳过内嵌字体,对标准字体与未嵌入 TrueType 字体调用PdfUsedFont.Replace()。 - 使用
PdfDocument.SaveToFile()保存结果文件,读出后触发浏览器下载。
替换 PDF 中字体的代码如下:
function App() {
const replaceFonts = async () => {
// 获取 Spire.PDF WASM 模块
const pdfModule = window.wasmModule?.spirepdf;
// 检查模块是否就绪
if (!pdfModule) {
alert('Spire.PDF is not ready yet');
return;
}
// 载入替换用的字体与示例 PDF
await window.spire.FetchFileToVFS('ARIALUNI.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
const inputFileName = 'Font_Sample.pdf';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/data/`);
// 创建 PdfDocument 对象并加载文档
const doc = new pdfModule.PdfDocument();
doc.LoadFromFile(inputFileName);
// UsedFonts 返回文档中用到的字体集合
const fonts = doc.UsedFonts;
const newFont = new pdfModule.PdfTrueTypeFont({
fontFamily: 'Arial Unicode MS',
size: 12,
style: pdfModule.PdfFontStyle.Regular,
unicode: true
});
// 逐个替换:Replace() 只支持标准 Type1 字体与未嵌入的 TrueType 字体
for (let i = 0; i < fonts.length; i++) {
const font = fonts.get(i);
// 内嵌字体无法替换,跳过
if (font.Type.value === pdfModule.PdfFontType.TrueTypeEmbedded.value) {
continue;
}
font.Replace(newFont);
}
// 保存结果文件
const outputFileName = 'ReplacedFonts.pdf';
doc.SaveToFile(outputFileName);
doc.Close();
// 从 VFS 读取生成的文件,触发下载
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'application/pdf' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Replace the Fonts Used in a PDF</h1>
<button onClick={replaceFonts}>
Replace fonts
</button>
</div>
);
}
export default App;
替换后,标准字体的文本改用新的 TrueType 字体,内嵌字体保持不变:

常见问题
替换后文字的字号和样式都变了,是怎么回事
原因:Replace() 接收的是一个完整的字体对象,替换时使用的是新对象自带的 size 与 style,原文各处文本原有的字号不会被保留。
解决:把目标字体的 size 与 style 设成替换后想要的值。例如希望结果统一为 12 磅常规体,就在 PdfTrueTypeFont 中传入 size: 12、style: PdfFontStyle.Regular。
替换后中文或日文显示成方框、问号
原因:目标字体没有对应字符的字形,或者构造 PdfTrueTypeFont 时没有启用 Unicode。
解决:换成覆盖目标语言字符的字体(如 Arial Unicode MS),构造时传入 unicode: true;字体文件要先加载到 VFS 的 /Library/Fonts/ 目录,Spire.PDF 才能嵌入它。
可以只替换其中一种字体吗
原因:UsedFonts 把文档中的字体逐个列出,Replace() 作用在单个 PdfUsedFont 上。
解决:遍历时按 Name 判断,只替换匹配的那一种:
for (let i = 0; i < fonts.length; i++) {
const font = fonts.get(i);
if (font.Name === 'ArialMT') {
font.Replace(newFont);
}
}
子集嵌入的字体名称可能带 BCDEEE+ 这类前缀,比较条件要按清单里实际读到的 Name 来写。
为什么调用 Replace() 报错,提示字体不是标准 Type 1 或未嵌入的 TrueType 字体
原因:PdfUsedFont.Replace() 只对标准 Type1 字体和未嵌入的 TrueType 字体生效。PDF 中常见的中日文字体多是子集嵌入的 TrueType(UsedFonts 里的类型显示为“内嵌 TrueType”),Spire.PDF 无法直接替换它们。
解决:遍历 UsedFonts 时按 Type 判断,只对标准字体与未嵌入的 TrueType 字体调用 Replace(),其余字体跳过;或者先准备一份使用标准字体、未嵌入字体的文档再处理。
获取免费许可证
如果您希望删除结果文档中的评估消息,或者摆脱功能限制,请该Email地址已收到反垃圾邮件插件保护。要显示它您需要在浏览器中启用JavaScript。获取有效期 30 天的临时许可证。









