告别乱码!pdfmake自定义字体完全指南:3步解决中文显示问题
你是否曾在使用pdfmake生成PDF时遇到中文显示为空白或乱码的问题?作为一款纯JavaScript的PDF生成库,pdfmake凭借其跨平台特性深受开发者喜爱,但字体配置一直是新手的"拦路虎"。本文将通过3个简单步骤,彻底解决中文显示难题,让你轻松掌握自定义字体的所有技巧。读完本文,你将能够:配置任意字体文件、解决中文显示问题、优化字体加载性能,并了解常见错误的排查方法。
一、认识pdfmake字体系统
pdfmake作为一款功能强大的PDF生成库,支持客户端和服务器端两种使用场景README.md。其核心优势包括丰富的文本格式化选项、表格支持、图片嵌入等,但字体管理需要特别配置才能正常显示中文等非西方字符。
字体工作原理
pdfmake使用虚拟文件系统(Virtual File System)管理字体资源,所有字体文件需要通过base64编码嵌入到PDF中。系统默认提供了Roboto字体src/browser-extensions/fonts/Roboto.js,但该字体不包含中文字符,这也是中文显示异常的根本原因。
// 字体配置示例(源自Roboto.js)
var fontContainer = {
vfs: {
'Roboto-Regular.ttf': { data: fs.readFileSync('path/to/font.ttf', 'base64'), encoding: 'base64' },
// 其他字重...
},
fonts: {
Roboto: {
normal: 'Roboto-Regular.ttf',
bold: 'Roboto-Medium.ttf',
italics: 'Roboto-Italic.ttf',
bolditalics: 'Roboto-MediumItalic.ttf'
}
}
};
字体配置结构
每个字体配置包含两个关键部分:
- vfs:虚拟文件系统,存储base64编码的字体文件
- fonts:字体定义,映射字重到vfs中的文件
二、3步实现中文显示
步骤1:准备字体文件
首先,选择一个支持中文的字体,如微软雅黑、思源黑体或Noto Sans SC。项目中已提供的示例字体位于examples/fonts/目录,包含了Roboto系列字体文件,但你需要添加中文字体文件到该目录。
步骤2:配置字体文件
创建自定义字体配置文件,参照src/browser-extensions/fonts/Roboto.js的结构,定义中文字体:
// 自定义中文字体配置
var ChineseFont = {
vfs: {
'SimHei.ttf': { data: 'base64编码的字体数据', encoding: 'base64' }
},
fonts: {
SimHei: {
normal: 'SimHei.ttf',
bold: 'SimHei.ttf', // 如果没有粗体版本,可复用常规版本
italics: 'SimHei.ttf',
bolditalics: 'SimHei.ttf'
}
}
};
// 添加字体到pdfmake
pdfmake.addFontContainer(ChineseFont);
步骤3:应用字体到文档
在文档定义中指定中文字体:
// 中文文档示例(修改自examples/basics.js)
var docDefinition = {
content: [
{ text: '中文标题', font: 'SimHei', fontSize: 20 },
{ text: '这是一段中文内容,现在可以正常显示了。', font: 'SimHei' }
],
defaultStyle: {
font: 'SimHei' // 设置全局默认字体
}
};
// 生成PDF
var pdf = pdfmake.createPdf(docDefinition);
pdf.write('pdfs/chinese-demo.pdf');
三、高级配置与优化
字体子集化
为减小PDF文件体积,可使用字体子集化工具只保留文档中实际使用的字符。这对于中文字体尤为重要,因为完整的中文字体文件通常较大。
多字体 fallback 配置
通过配置字体栈,实现当某个字符在当前字体中不存在时,自动使用后备字体:
var docDefinition = {
content: [
{ text: '混合文本:English and 中文', font: 'SimHei, Roboto' }
]
};
常见问题排查
- 字体不生效:检查字体文件路径和base64编码是否正确
- 文件体积过大:实施字体子集化,只包含必要字符
- 服务器端 vs 客户端差异:服务器端可直接读取文件系统examples/basics.js,客户端需要手动编码字体文件
四、完整示例代码
以下是一个完整的中文PDF生成示例,整合了上述所有技巧:
// 完整中文配置示例
var pdfmake = require('../js/index');
var fs = require('fs');
// 读取中文字体文件并编码为base64
function getFontData(path) {
return fs.readFileSync(path, 'base64');
}
// 配置中文字体
pdfmake.addFonts({
SimHei: {
normal: { data: getFontData('examples/fonts/SimHei.ttf'), encoding: 'base64' },
bold: { data: getFontData('examples/fonts/SimHei.ttf'), encoding: 'base64' },
italics: { data: getFontData('examples/fonts/SimHei.ttf'), encoding: 'base64' },
bolditalics: { data: getFontData('examples/fonts/SimHei.ttf'), encoding: 'base64' }
}
});
// 创建中文文档
var docDefinition = {
content: [
{ text: 'pdfmake中文显示示例', font: 'SimHei', fontSize: 18, bold: true },
{ text: '这是一段包含中文的PDF内容,现在可以完美显示了!', font: 'SimHei', fontSize: 12 },
{
text: '表格中的中文也没有问题:',
font: 'SimHei',
margin: [0, 10, 0, 5]
},
{
table: {
body: [
['表头1', '表头2'],
['内容1', '内容2'],
['中文内容', '表格测试']
]
},
style: { font: 'SimHei' }
}
]
};
// 生成PDF文件
pdfmake.createPdf(docDefinition).write('pdfs/chinese-complete-example.pdf')
.then(() => console.log('PDF生成成功'))
.catch(err => console.error('生成失败:', err));
总结与展望
通过本文介绍的3个步骤,你已经掌握了pdfmake自定义字体的核心技巧,成功解决了中文显示问题。字体配置虽然看似简单,但却是实现专业PDF输出的关键一步。随着pdfmake的不断更新,字体管理功能也在持续优化,未来可能会提供更简便的中文字体集成方案。
现在就动手尝试,为你的PDF添加漂亮的中文字体吧!如有任何问题,欢迎在评论区留言讨论。别忘了点赞收藏,关注获取更多pdfmake使用技巧!
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



