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

XDocReport生成PDF时西里尔文字符间距异常问题求助

解决DOCX转PDF时西里尔字符粘连、间距异常问题

将含变量的DOCX模板转换为PDF时,英文字符显示正常,但西里尔文字符出现粘连、字符间距异常。尝试修改pdfWriter.setSpaceCharRatio未生效,DOCX模板本身格式正常。相关代码、调用方式及依赖配置如下:

原服务端方法

public static void generateReport(InputStream docxInputStream, OutputStream pdfOutputStream) throws Exception {
    IXDocReport report = XDocReportRegistry.getRegistry().loadReport(docxInputStream, TemplateEngineKind.Freemarker);
    IContext context = report.createContext();

    Options options = Options.getFrom(DocumentKind.DOCX).via(ConverterTypeVia.XWPF).to(ConverterTypeTo.PDF);

    PdfOptions pdfOptions = PdfOptions.create()
            .fontEncoding("windows-1251")
            .fontProvider((s, s1, v, i, color) -> FontFactory.getFont(FontFactory.TIMES_ROMAN, "windows-1251", v, i, color));

    options.subOptions(pdfOptions);
    report.convert(context, options, pdfOutputStream);
}

原调用代码

FileInputStream docxInputStream = new FileInputStream("/abspath/resources/template.docx");
FileOutputStream pdfOutputStream = new FileOutputStream("/abspath/resources/output.pdf");
ReportGenerator.generateReport(docxInputStream, pdfOutputStream);
docxInputStream.close();
pdfOutputStream.close();

原Maven依赖

<dependency>
    <groupId>fr.opensagres.xdocreport</groupId>
    <artifactId>xdocreport</artifactId>
    <version>2.0.2</version>
</dependency>
<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.32</version>
</dependency>
<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity</artifactId>
    <version>1.7</version>
</dependency>
<dependency>
    <groupId>com.lowagie</groupId>
    <artifactId>itext</artifactId>
    <version>2.1.7</version>
</dependency>

<dependency>
    <groupId>fr.opensagres.xdocreport</groupId>
    <artifactId>fr.opensagres.poi.xwpf.converter.pdf</artifactId>
    <version>2.0.2</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>4.0.1</version>
</dependency>

解决方法

问题核心是当前使用的TIMES_ROMAN字体不完整支持西里尔字符,导致渲染时字符布局异常。可通过以下步骤修复:

1. 替换为支持西里尔文的字体

选择内置支持西里尔字符的字体,比如Times New Roman(需确保系统中存在该字体),或使用开源字体如DejaVu Serif。修改字体提供者配置:

  • 依赖系统字体的方式:
    .fontProvider((s, s1, v, i, color) -> FontFactory.getFont("Times New Roman", "UTF-8", v, i, color))
    
  • 嵌入字体文件(避免依赖系统环境):
    将字体文件(如DejaVuSerif.ttf)放入项目resources目录,加载逻辑如下:
    .fontProvider((s, s1, v, i, color) -> {
        InputStream fontStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("DejaVuSerif.ttf");
        BaseFont baseFont = BaseFont.createFont("DejaVuSerif.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
        return new Font(baseFont, v, i, color);
    })
    

2. 调整编码为UTF-8

DOCX文件本身采用UTF-8编码存储,将fontEncoding从windows-1251改为UTF-8,避免编码不匹配导致的字符解析错误:

PdfOptions pdfOptions = PdfOptions.create()
        .fontEncoding("UTF-8")
        .fontProvider(...); // 上述修改后的字体提供者

3. 确保字体正确嵌入

使用BaseFont.EMBEDDED参数嵌入字体,保证PDF在无对应字体的环境下也能正常显示西里尔字符。


修改后的完整代码

public static void generateReport(InputStream docxInputStream, OutputStream pdfOutputStream) throws Exception {
    IXDocReport report = XDocReportRegistry.getRegistry().loadReport(docxInputStream, TemplateEngineKind.Freemarker);
    IContext context = report.createContext();

    Options options = Options.getFrom(DocumentKind.DOCX).via(ConverterTypeVia.XWPF).to(ConverterTypeTo.PDF);

    PdfOptions pdfOptions = PdfOptions.create()
            .fontEncoding("UTF-8")
            .fontProvider((s, s1, v, i, color) -> {
                InputStream fontStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("DejaVuSerif.ttf");
                BaseFont baseFont = BaseFont.createFont("DejaVuSerif.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
                return new Font(baseFont, v, i, color);
            });

    options.subOptions(pdfOptions);
    report.convert(context, options, pdfOutputStream);
}

额外说明

若使用DejaVu字体,可通过Maven添加依赖(无需手动下载字体文件):

<dependency>
    <groupId>com.github.librepdf</groupId>
    <artifactId>openpdf-fonts</artifactId>
    <version>1.3.30</version>
</dependency>

内容的提问来源于stack exchange,提问作者Яков Клюев

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 12:55:13