ITextRenderer/FlyingSaucer生成PDF无法显示中、泰米尔、阿拉伯字符求助
解决FlyingSaucer/ITextRenderer生成PDF时多语言字符(中文、泰米尔文、阿拉伯文)不显示的问题
核心问题分析
FlyingSaucer渲染PDF时的字体处理逻辑和浏览器不一样,就算CSS指定了字体,也常因为字体没正确嵌入、字体文件不包含目标字符集、版本冲突导致非拉丁字符缺失,HTML显示正常但PDF丢字就是典型表现。
解决方案
1. 用对应语言的专用Noto字体
基础版Noto Sans不包含所有非拉丁字符,中文得用Noto Sans SC,泰米尔文用Noto Sans Tamil,阿拉伯文用Noto Sans Arabic,单一字体覆盖不了所有场景。
- 下载对应语言的字体包放到项目字体目录
- CSS里用字体栈覆盖多语言场景:
@font-face { font-family: 'Noto Sans SC'; font-weight: 400; font-style: normal; src: url('../../fonts/NotoSansSC-Regular.ttf'); -fs-pdf-font-embed: embed; -fs-pdf-font-encoding: Identity-H; } @font-face { font-family: 'Noto Sans Tamil'; font-weight: 400; font-style: normal; src: url('../../fonts/NotoSansTamil-Regular.ttf'); -fs-pdf-font-embed: embed; -fs-pdf-font-encoding: Identity-H; } @font-face { font-family: 'Noto Sans Arabic'; font-weight: 400; font-style: normal; src: url('../../fonts/NotoSansArabic-Regular.ttf'); -fs-pdf-font-embed: embed; -fs-pdf-font-encoding: Identity-H; } .name { padding: 4px 16px; font-family: 'Noto Sans SC', 'Noto Sans Tamil', 'Noto Sans Arabic', sans-serif; width: 50%; }
2. 直接用Java代码注册字体(比CSS可靠)
CSS加载字体容易因为路径、权限出问题,用FontResolver手动注册更稳:
ITextRenderer renderer = new ITextRenderer(); // 单个注册字体文件 renderer.getFontResolver().addFont("src/main/resources/fonts/NotoSansSC-Regular.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED); renderer.getFontResolver().addFont("src/main/resources/fonts/NotoSansTamil-Regular.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED); renderer.getFontResolver().addFont("src/main/resources/fonts/NotoSansArabic-Regular.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED); // 或者批量注册整个目录的字体 renderer.getFontResolver().addFonts("src/main/resources/fonts/", true); // 执行PDF渲染 renderer.setDocumentFromString(htmlContent); renderer.layout(); renderer.createPDF(outputStream);
注意:CSS里的font-family要和字体文件的真实名称一致(右键字体文件看属性就能找到)。
3. 修复依赖版本冲突
你当前用的flying-saucer-pdf:9.1.22依赖iText 5.x,但手动引入了iText 8.0.1,版本不兼容会直接搞崩字体解析:
- 要么删掉单独的iText kernel、layout、html2pdf依赖,用FlyingSaucer自带的兼容版本:
<dependency> <groupId>org.xhtmlrenderer</groupId> <artifactId>flying-saucer-pdf</artifactId> <version>9.1.22</version> </dependency>
- 要么改用适配iText 8的FlyingSaucer版本:
<dependency> <groupId>org.xhtmlrenderer</groupId> <artifactId>flying-saucer-pdf-itext8</artifactId> <version>9.1.22</version> </dependency>
4. 确认字体文件有效且打包正确
- 打开字体文件预览,确认包含要显示的字符(比如中文“额”),避免下载的文件损坏
- Maven项目要配置资源插件,确保字体文件被打包到classpath:
<build> <resources> <resource> <directory>src/main/resources/fonts</directory> <includes> <include>*.ttf</include> </includes> </resource> </resources> </build>
5. 处理阿拉伯文的RTL布局
阿拉伯文是从右到左排版,要加CSS属性:
.arabic-text { direction: rtl; unicode-bidi: embed; }
验证步骤
- 先通过Java代码注册字体,确认路径正确
- 简化HTML结构,只留测试字符,排除其他样式干扰
- 生成PDF后查看文档属性的字体列表,确认Noto字体已嵌入
内容的提问来源于stack exchange,提问作者ShengisBored
相关产品推荐
相关产品推荐

