使用itext踩过的坑

时间:2024-04-13 13:31:14

说明:很多时候我们会使用itext 来导出pdf。其实我们最关心的无非是两个问题。1.如何快速使用itext导出pdf。2.使用哪个版本以及能否支持中文。

第一点我将在下一篇文章中写自己开发了一套报表打印后的收获,以及代码。这里主要说第二点。下面我先贴一段代码(这个是我从网上搜来的)。

Document document = new Document();
File file = new File("chinese.pdf");
System.out.println(file.getAbsolutePath());
OutputStream os = new FileOutputStream(file);
PdfWriter.getInstance(document,os);
document.open();
//方法一:使用Windows系统字体(TrueType)
//BaseFont baseFont = BaseFont.createFont("C:/Windows/Fonts/SIMYOU.TTF",BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);

//方法二:使用iTextAsian.jar中的字体
//BaseFont baseFont = BaseFont.createFont("STSong-Light",BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);

//方法三:使用资源字体(ClassPath)
String resourcePath ="/Users/nsh/IdeaProjects/dingcw/dingfinance-app/src/main/resources/font/simhei.ttf";
String mainPath = "/Users/nsh/IdeaProjects/dingcw/dingfinance-app/src/main/java/com/raycloud/dingfinance/app/simhei.ttf";
String targetPath ="/Users/nsh/IdeaProjects/dingcw/dingfinance-app/target/classes/font/simhei.ttf";
String absPath = "font/simhei.ttf";
BaseFont baseFont = BaseFont.createFont(targetPath,BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);

Font font = new Font(baseFont);
document.add(new Paragraph("解决中文问题了!",font));
document.close();

我觉得这个就是最简单的也是最经典的导出pdf的实现方式。其中第一种我没有试,因为我是mac。后面两个都试过是可以的,但是这里有一些坑需要注意。

1.使用方法二导出时,你可能会报错,如果你起网上查,好多是告诉你 编译然后修改itext的文件名称。其实完全不需要,只要看看自己项目中现在用的是哪个版本,我用的这两个版本是可以的。

<!-- itextpdf 导出pdf -->
<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itextpdf</artifactId>
    <version>5.5.11</version>
</dependency>
<!-- pdf导出中文需要用到 -->
<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itext-asian</artifactId>
    <version>5.2.0</version>
</dependency>

如果你也换成了这两个版本还是不支持中文(具体的异常信息就不贴了),请注意你的maven依赖中是否有其他组件也内含了itext相关的jar,这个我当时也遇到了,头疼的要死。为什么别人的可以我的不行呢,后来仔细找maven中的依赖发现了问题。

<dependency>
    <groupId>com.qumoon</groupId>
    <artifactId>qumoon-job-queue</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
        </exclusion>
        <exclusion>
            <groupId>com.lowagie</groupId>
            <artifactId>itext</artifactId>
        </exclusion>
    </exclusions>
</dependency>

在我引用的 qumoon-job-queue中也有itext,而他里边的是比较旧的版本,这里我们需要配置一个 <exclusion></exclusion> 如上图,将itext相关的忽略掉。如果去除掉其他版本的干扰,这个时候你应该已经可以使用第二种方法导出中文的pdf了。但是还有个小问题,就是我们用的这个是iTextAsian.jar的中文字体。这个字体显示中文没问题,但是显示数字时数字之间的间距太小了,而且在部分xp系统中数字格式会完全乱掉(生产环境客户实际反馈的问题使用itext踩过的坑

所以我们需要使用其他字体去显示,所以有了第三种实现方式。

2.第三种方式是我们使用自己的字体(支持中文的)去显示,这里也有一些问题。

(1).不要把 字体文件放在resource目录下,因为经过maven打包到target后文件部分内容会被替换,这里我是用python对打包前后的文件做了对比,果然发生了变化使用itext踩过的坑

因为这个字体文件中可能有一些我们项目中其他配置文件的关键字,所以会被替换掉。这样就导致itext初始化字体失败。但是这个路径可以使用绝对路径,也可以使用相对路径,但是注意不要放在resource目录下。我是放在webapp目录下了。我项目中用的字体文件是黑体,比之前的数字显示会好很多。另外如果你使用第三种方式还报错,请仔细看下错误信息如果是报文件不存在还是资源解析失败。因为itext写死了是从字体文件中取"name"属性(打断点从源码中可以看到),所以确保你的字体文件是正确的而且没有放到resource目录下。

这是我导出pdf遇到的问题,希望对你有所帮助。