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
相关产品推荐
相关产品推荐

