记录 Apache PDFBox 的简单使用,以及解决遇到的各种问题。

用 Apache PDFBox 来生成PDF文件,此文是简单的一个Demo,并记录首次使用时遇到的问题,更多高级用法,请参考官网。

1. Maven配置依赖

<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>pdfbox</artifactId>
    <version>2.0.17</version>
</dependency>

2. 使用PDFBox API创建pdf对象

PDDocument doc = new PDDocument();
PDPage page = new PDPage();
doc.addPage(page);
PDPageContentStream pageContent = new PDPageContentStream(doc, page);
pageContent.beginText();
//加载宋体ttf,支持中文
File fontFile = new File(this.getClass().getResource("/").getPath() + "fonts/SIMFANG.TTF");
PDType0Font font = PDType0Font.load(doc, fontFile);
pageContent.setFont(font, 20);
//行间距
pageContent.setLeading(20);
//新行的偏移量
pageContent.newLineAtOffset(45, PDRectangle.A4.getHeight() - 90);
pageContent.showText("字段名称-1: 字段值");
pageContent.newLine();
pageContent.showText("字段名称-2 : 111111111");
pageContent.newLine();
pageContent.endText();
//必须关
pageContent.close();
//保存本地
doc.save("/test/test.pdf");
//如果你要上传到文件服务器,可以直接用下面这种方式获取InputStream
//ByteArrayOutputStream out = new ByteArrayOutputStream();
//doc.save(out);
//ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
doc.close();

3. 生成PDF效果图

4. 期间遇到的几个问题以及解决方法

4.1 ('.notdef') is not available in this font Courier-Bold encoding: WinAnsiEncoding

U+59D3 ('.notdef') is not available in this font Courier-Bold encoding: WinAnsiEncoding
方式一、服务器安装中文字体

请自行搜索.... 没采用这种原因主要是嫌麻烦,需要在每台服务器去安装,虽然可以搞个脚本之类批量进行安装。

方式二、代码手动加载宋体ttf文件

把ttf放到resource目录下,打包到jar/war中

SIMFANG.TTF 可以在Windows系统的C盘上找到,如果是Mac用户可以找Windows的要一个

File fontFile = new File(Objects.requireNonNull(this.getClass().getResource("/")).getPath() + "fonts/SIMFANG.TTF");
PDType0Font font = PDType0Font.load(doc, fontFile);

4.2 head is mandatory

由于打包时,ttf文件貌似被编译了,也就是破坏了ttf的内容,导致解析ttf失败。解决方法是不对ttf文件做编译。

java.io.IOException: head is mandatory
at org.apache.fontbox.ttf.TTFParser.parseTables(TTFParser.java:182)
at org.apache.fontbox.ttf.TTFParser.parse(TTFParser.java:150)
at org.apache.fontbox.ttf.TTFParser.parse(TTFParser.java:87)
at org.apache.pdfbox.pdmodel.font.PDType0Font.load(PDType0Font.java:67)
方式一、 使用maven-assembly-plugin方式
<fileSet>
    <directory>src/main/resources</directory>
    <excludes>
        <exclude>fonts/*</exclude> <!-- 打包时暂时排除掉 fonts/*.ttf-->
    </excludes>
    <outputDirectory>/conf</outputDirectory>
    <filtered>true</filtered> <!-- 会做maven的properties的属性替换 -->
</fileSet>
<fileSet>
    <directory>src/main/resources</directory>
    <includes>
        <include>fonts/*</include> <!-- 单独对fonts/*.ttl 做打包 -->
    </includes>
    <outputDirectory>/conf</outputDirectory>
    <filtered>false</filtered> <!-- 不会做替换 -->
</fileSet>
方式二、使用maven-resources-plugin方式
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-resources-plugin</artifactId>
    <version>2.4.3</version>
    <configuration>
        <nonFilteredFileExtensions>
            <nonFilteredFileExtension>ttf</nonFilteredFileExtension>
        </nonFilteredFileExtensions>
    </configuration>
</plugin>