Primefaces DataExporter阿拉伯文显示错乱问题求助
PrimeFaces DataExporter 导出PDF时阿拉伯文字符显示异常的解决办法
我在项目中使用PrimeFaces的DataExporter组件导出PDF时,遇到阿拉伯文字符显示异常的问题——这些字符要么完全不显示,要么呈现为分散、上下堆叠的错乱状态。
我曾尝试通过PDFOptions引入Arial字体,代码如下:
pdfOpt = new PDFOptions(); InputStream fontStream = FacesContext.getCurrentInstance().getExternalContext().getResourceAsStream("/resources/fonts/arial.ttf"); BaseFont baseFont = null; try { baseFont = BaseFont.createFont("arial.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, true, fontStream.readAllBytes(), null); } catch (IOException ex) { Logger.getLogger(PrimefacesPDFExporterOptions.class.getName()).log(Level.SEVERE, null, ex); } catch (DocumentException ex) { Logger.getLogger(PrimefacesPDFExporterOptions.class.getName()).log(Level.SEVERE, null, ex); } Font font = new Font(baseFont, 12, Font.NORMAL); pdfOpt.setFontName(font.getBaseFont().getFullFontName()[0][3]);
但这种方式只能设置字体名称,无法直接配置字体本身。之后我又在<p:dataExporter>标签中添加了encoding="Identity-H"属性:
<p:dataExporter options="#{primefacesPDFExporterOptions.pdfOpt}" encoding="Identity-H" type="pdf" preProcessor="#{primefacesPDFExporterOptions.makePDFLandscape}" pageOnly="false" target="explorerResultsTableId" fileName="data"/>
问题依然没有解决,尝试修改PDF每个单元格的字体时,又无法获取到单元格对象,求可行的解决办法。
解决办法
1. 换用支持阿拉伯语的字体并正确嵌入
先确认你用的字体真的支持阿拉伯文,比如Arial Unicode MS、Amiri这类,把字体文件放到项目resources/fonts目录下。
2. 自定义PDFExporter扩展类
默认的DataExporter没法直接控制单元格字体,所以得自己写个扩展类,重写单元格的渲染逻辑:
public class CustomPDFExporter extends PDFExporter { private BaseFont arabicFont; public CustomPDFExporter() { try { InputStream fontStream = FacesContext.getCurrentInstance().getExternalContext().getResourceAsStream("/resources/fonts/arial-unicode-ms.ttf"); arabicFont = BaseFont.createFont("arial-unicode-ms.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, true, fontStream.readAllBytes(), null); } catch (Exception e) { e.printStackTrace(); } } @Override protected void exportCell(FacesContext context, DataTable table, UIColumn column, String value, PdfPTable pdfTable, int index) throws IOException { Font font = new Font(arabicFont, 12, Font.NORMAL); PdfPCell cell = new PdfPCell(new Phrase(value != null ? value : "", font)); // 阿拉伯文是从右到左,必须设置这个属性 cell.setRunDirection(PdfWriter.RUN_DIRECTION_RTL); pdfTable.addCell(cell); } }
3. 后台Bean里调用自定义导出逻辑
别用页面的<p:dataExporter>了,直接在Bean里写导出方法:
public void exportToPDF() { FacesContext context = FacesContext.getCurrentInstance(); DataTable table = (DataTable) context.getViewRoot().findComponent("explorerResultsTableId"); CustomPDFExporter exporter = new CustomPDFExporter(); exporter.setFileName("data.pdf"); exporter.setPageOnly(false); // 设为横向,和你之前的需求一致 exporter.setPreProcessor(document -> { document.setPageSize(PageSize.A4.rotate()); }); exporter.export(context, table, "data.pdf", false, false, "UTF-8", null, null); }
4. 页面按钮触发导出
用普通的commandButton调用这个方法就行:
<p:commandButton value="导出PDF" action="#{yourBean.exportToPDF}" ajax="false" />
重点提醒
- 字体必须嵌入,而且要支持阿拉伯文,不然编码设置对了也白搭。
- 阿拉伯文是RTL语言,一定要给单元格设置
RUN_DIRECTION_RTL,不然文字顺序会乱。 - 自定义导出器是核心,能直接控制每个单元格的渲染细节,解决默认组件的局限性。
内容的提问来源于stack exchange,提问作者Ali Khaddour
相关产品推荐
相关产品推荐

