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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 13:35:23