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

SpringBoot生成PDF中文缺失求助(Thymeleaf+Flying-saucer)

排查与修复Flying Saucer PDF中文缺失问题

以下是针对你的问题的具体排查方向和修复方案:

一、确认字体加载逻辑正确性

很多情况下中文缺失并非字体本身问题,而是字体未被正确加载到Flying Saucer的渲染上下文:

  1. 字体文件路径与打包验证

    • 将字体文件(如SimSun.ttf、NotoSansSC-Regular.ttf)放置在src/main/resources/fonts目录下
    • 打包后检查jar包内是否包含字体文件:执行jar -tf your-springboot-app.jar,确认存在BOOT-INF/classes/fonts/[字体文件名]
    • 注意:Linux环境下文件名大小写敏感,确保代码中引用的文件名与实际一致
  2. 正确注册字体(适配Jar包环境)
    避免使用getFile()方法(Jar内无法直接获取文件路径),改用流加载方式:

    ITextRenderer renderer = new ITextRenderer();
    // 加载SimSun字体
    try (InputStream fontStream = getClass().getResourceAsStream("/fonts/SimSun.ttf")) {
        if (fontStream == null) {
            throw new IOException("字体文件未找到");
        }
        renderer.getFontResolver().addFont(
            fontStream,
            BaseFont.IDENTITY_H, // 必须用IDENTITY_H支持Unicode全字符集
            BaseFont.EMBEDDED // 嵌入字体到PDF,避免依赖客户端字体
        );
    }
    

二、CSS字体规则强制生效

确保HTML中的所有中文元素都正确关联到加载的中文字体:

  1. 全局字体覆盖
    在Thymeleaf模板的<style>标签中设置全局字体:

    <style>
        * {
            font-family: 'SimSun', 'Noto Sans SC', serif !important;
        }
        body {
            font-size: 12pt;
            color: #333;
        }
    </style>
    
    • 使用!important避免其他CSS规则覆盖字体设置
    • 按优先级排列字体,优先使用已加载的中文字体
  2. 验证HTML字符编码
    确保HTML头部声明UTF-8编码,避免字符转义问题:

    <meta charset="UTF-8">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    

三、排查其他潜在问题

  1. 字体文件完整性
    重新下载官方字体文件(如从系统字体目录复制SimSun,或获取官方版本的Noto Sans SC),避免使用损坏的字体文件

  2. Flying Saucer版本兼容性
    升级到最新稳定版(如9.1.22),旧版本可能存在中文字体渲染Bug:

    <dependency>
        <groupId>org.xhtmlrenderer</groupId>
        <artifactId>flying-saucer-pdf</artifactId>
        <version>9.1.22</version>
    </dependency>
    
  3. PDF字体嵌入验证
    生成PDF后,用Adobe Acrobat或其他PDF阅读器查看文档属性→字体列表,若能看到SimSun或Noto Sans SC,说明字体已成功嵌入;若未显示,需重新检查字体加载逻辑

四、完整示例代码

SpringBoot服务中的PDF生成核心逻辑:

@Service
public class PdfService {
    private final TemplateEngine templateEngine;

    public PdfService(TemplateEngine templateEngine) {
        this.templateEngine = templateEngine;
    }

    public ByteArrayInputStream generateChinesePdf(String templateName, Map<String, Object> data) throws Exception {
        // 生成HTML内容
        Context context = new Context(Locale.CHINA);
        context.setVariables(data);
        String html = templateEngine.process(templateName, context);

        // 初始化渲染器并加载字体
        ITextRenderer renderer = new ITextRenderer();
        try (InputStream simSunStream = getClass().getResourceAsStream("/fonts/SimSun.ttf")) {
            renderer.getFontResolver().addFont(simSunStream, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
        }

        // 渲染并生成PDF
        renderer.setDocumentFromString(html);
        renderer.layout();
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        renderer.createPDF(outputStream);
        return new ByteArrayInputStream(outputStream.toByteArray());
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 02:56:20