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

Spring Boot生成含阿拉伯语PDF发票问题求助(Jasper/Thymeleaf)

解决Spring Boot 2.7.5导出含阿拉伯语(摩洛哥)发票PDF的问题

一、JasperReport 资源包问号+字体无效问题修复

1. 资源包编码问题

默认properties文件编码非UTF-8会导致阿拉伯语字符显示为问号,按以下步骤调整:

  • 在application.properties中添加编码配置:
    spring.messages.encoding=UTF-8
    spring.messages.basename=messages_ar_MA
    
  • 确保messages_ar_MA.properties文件保存为UTF-8编码(IDE中设置文件编码为UTF-8,无需手动转义字符)。
  • 加载资源包时显式指定编码:
    ResourceBundle bundle = ResourceBundle.getBundle("messages_ar_MA", new Locale("ar", "MA"), new UTF8Control());
    
    // 自定义UTF8Control类,强制用UTF-8读取资源文件
    static class UTF8Control extends ResourceBundle.Control {
        @Override
        public InputStream newInputStream(String baseName, Locale locale) throws IOException {
            String resourcePath = toResourceName(toBundleName(baseName, locale), "properties");
            return Thread.currentThread().getContextClassLoader().getResourceAsStream(resourcePath);
        }
    }
    

2. 字体嵌入与配置

仅安装系统字体无效,需在Jasper模板中嵌入支持阿拉伯语的字体(如Noto Naskh Arabic、Amiri):

  • 将字体文件(如NotoNaskhArabic-Regular.ttf)放到resources/fonts目录下。
  • 在Jasper模板的字体属性中配置:
    <font fontName="Noto Naskh Arabic" pdfFontName="fonts/NotoNaskhArabic-Regular.ttf" pdfEncoding="Identity-H" pdfEmbedded="true"/>
    
  • 代码中注册字体扩展:
    FontExtensionsRegistry.getInstance().registerFont(new FontFamily() {
        @Override
        public String getName() {
            return "Noto Naskh Arabic";
        }
        @Override
        public String getNormalFont() {
            return "fonts/NotoNaskhArabic-Regular.ttf";
        }
        // 按需实现粗体、斜体字体路径返回
    });
    

二、Thymeleaf + Flying-Saucer 阿拉伯语不显示问题修复

1. HTML模板配置

确保模板中正确引入字体并设置RTL(从右到左)文本方向:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/>
    <style>
        @font-face {
            font-family: 'Noto Naskh Arabic';
            src: url('classpath:/fonts/NotoNaskhArabic-Regular.ttf') format('truetype');
            font-weight: normal;
            font-style: normal;
        }
        .arabic-content {
            font-family: 'Noto Naskh Arabic', serif;
            direction: rtl;
            unicode-bidi: embed;
        }
    </style>
</head>
<body>
    <div class="arabic-content" th:text="${invoiceLabel}"></div>
</body>
</html>

2. Flying-Saucer 渲染配置

生成PDF时需主动嵌入字体并指定编码:

@Autowired
private TemplateEngine templateEngine;

public void exportInvoicePdf(HttpServletResponse response) throws Exception {
    Context context = new Context();
    context.setVariable("invoiceLabel", "فاتورة مُثال"); // 正确的阿拉伯语文本

    String renderedHtml = templateEngine.process("invoice-template", context);

    ITextRenderer renderer = new ITextRenderer();
    // 添加字体到解析器,确保嵌入PDF
    renderer.getFontResolver().addFont("classpath:/fonts/NotoNaskhArabic-Regular.ttf", "Identity-H", true);
    renderer.setDocumentFromString(renderedHtml);
    renderer.layout();

    response.setContentType("application/pdf");
    response.setHeader("Content-Disposition", "attachment; filename=invoice_ar.pdf");
    renderer.createPDF(response.getOutputStream());
}

3. 关键注意点

  • 确保Thymeleaf模板渲染输出为UTF-8编码,可在配置类中设置:
    @Bean
    public ServletContextTemplateResolver templateResolver() {
        ServletContextTemplateResolver resolver = new ServletContextTemplateResolver();
        resolver.setCharacterEncoding("UTF-8");
        resolver.setPrefix("/WEB-INF/templates/");
        resolver.setSuffix(".html");
        return resolver;
    }
    
  • 禁止依赖系统默认字体,必须嵌入支持阿拉伯语的字体,Flying-Saucer默认字体不包含阿拉伯语字符集。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 06:45:37