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

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;
}

验证步骤

  1. 先通过Java代码注册字体,确认路径正确
  2. 简化HTML结构,只留测试字符,排除其他样式干扰
  3. 生成PDF后查看文档属性的字体列表,确认Noto字体已嵌入

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 19:40:05