【Java,PDF】使用Itext实现PDF文件生成

有时需要在java端实现pdf文件的生成功能,完成类似条款说明、签名、协议等pdf下载需求时,不得不使用Java来实现对pdf文件的生成,本文简单的介绍了如何使用Itext在java端生成PDF文件。

【Java,PDF】使用Itext实现PDF文件生成

By img Microanswer Create at:Jul 9, 2019, 10:57:47 AM 

Tags: java pdf itext

有时需要在java端实现pdf文件的生成功能,完成类似条款说明、签名、协议等pdf下载需求时,不得不使用Java来实现对pdf文件的生成,本文简单的介绍了如何使用Itext在java端生成PDF文件。


重要声明:本文章仅仅代表了作者个人对此观点的理解和表述。读者请查阅时持自己的意见进行讨论。

前言

有时候,业务系统要求提供一个PDF文件导出的功能,这时候我们就需要将数据库的对应数据查询出来,然后生成PDF并提供下载,这其中比较陌生的部分相信就是如何使用这些数据生成一个PDF文件了,本文讲述了使用 Itext 在Java后端生成PDF的方法,不妨来看看一吧。

一、加入依赖

Itext 的官方地址是:https://itextpdf.com

首要第一步则是加入Itext的依赖,然后才可以使用相关的操作类。Itext 的依赖不是都在一个包里,它分了许许多多模块,但基本的生成PDF的依赖包只需要引入2个即可。

首先是核心包:

<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itextpdf</artifactId>
    <version>5.5.13</version>
</dependency>

然后需要引入对中文支持的包,毕竟大部分文档中都会有中文内容的。

<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itext-asian</artifactId>
    <version>5.2.0</version>
</dependency>

只需要引入这两个包,就可以完成基本的生成PDF操作了。

二、开始使用

Itext 的用法十分简单,大致可以分为下面几步:

  1. 构建文档
  2. 打开文档编辑功能
  3. 插入文档内容
  4. 关闭文档编辑功能

1、构建文档

Itext 构建文档是通过 Document 类进行构建,不过要注意,大多数项目里面应该存在许多个 Document 类了,这里一定要使用 com.itextpdf.text 包下面的 Document 类。这个类包含一个无参构造函数,意味着可以十分方便的 new 一个空文档出来:

Document document = new Document();

默认创建的是 A4 纸大小、内边距 36 的PDF文档。如果你希望创建不同大小以及不同边距的文档,你可以使用带参构造函数:

Document documentA8   = new Document(PageSize.A8);
Document documentA8_2 = new Document(PageSize.A8, 10, 10, 10,10);

这里构建了 2 个文档,第一个文档设定了大小为 A8 纸张大小, 第二个文档设定了边距为 10,这些边距值分别对应左, 右, 上, 下。构建好了文档,就可以开始进行文档编辑了。

2、 打开文档编辑功能

在编辑之前,需要先认识一个类 PdfWriter,这个类帮助我们打开文档的编辑功能,同时能指定将pdf文件输出到对应的输出流里面,意味着我们如果使用文件输出流,它就可以将pdf文件输出到文件中。

Document document = new Document();
PdfWriter.getInstance(document, new FileOutputStream("D:/test.pdf"));
document.open();

使用 PdfWriter.getInstance 方法可以将文件到指定输出流,传入文件输出流可实现输出到文件。然后调用 document.open 方法打开编辑功能,只有调用了此方法之后,才可以对 document 进行编辑。

3、 插入内容及中文

现在,可以放心的向文档中插入内容了,不如先插入一个段落在文档中试一试, 使用 com.itextpdf.text.Paragraph 类可以实现对段落的构建,先来看个效果:

Document document = new Document();
PdfWriter.getInstance(document, new FileOutputStream("D:/test.pdf"));
document.open();

// 新建一个段落,内容 Hello Pdf.
Paragraph p1 = new Paragraph("Hello Pdf.");
document.add(p1);

document.close();

最后不要忘了执行关闭。打开D盘,发现文件test.pdf,效果如图:

图1

似乎非常完美,但当我把 “Hello” 改成 “你好”后,再一次生成文档:

Document document = new Document();
PdfWriter.getInstance(document, new FileOutputStream("D:/test.pdf"));
document.open();
Paragraph p1 = new Paragraph("你好 Pdf.");
document.add(p1);
document.close();

再次运行,得到效果:

图2

发现中文并没有被显示出来,这时候就需要用到刚才添加的第二个依赖了。要让中文显示正常,需要借助中文字体来实现这个需求,itext-asian 包内置了一个中文字体提供使用。建立使用 itext-asian 内置中文支持:

BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
Font mfont = new Font(bfChinese, 15, Font.NORMAL, BaseColor.BLACK);

首先使用内置字体建立基本字体类型,然后建立段落可以使用的字体对象,最后,mfont 对象就可以传递给 Paragraph,从而实现中文支持。代码如下:

BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
Font mfont = new Font(bfChinese, 15, Font.NORMAL, BaseColor.BLACK);

Document document = new Document();
PdfWriter.getInstance(document, new FileOutputStream("D:/test.pdf"));
document.open();

Paragraph p1 = new Paragraph("你好 Pdf.", mfont);
document.add(p1);

document.close();

运行效果图如下:

图3.

有时候这个字体并不能满足需求,你可以自己使用自己的字体文件来实现个性化字体:

// 使用window内置的等线字体
BaseFont.createFont("C:/Windows/Fonts/Deng.ttf", BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);

// 使用自己的字体文件
BaseFont.createFont("D:/思源黑体正常字体.ttf", BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);

三、Itext 提供的各种文档组件

上面简单的介绍了段落使用方法,其实Itext除了段落组件,还提供了许多其他的组件封装,比较常用的组件见下表:

介绍
com.itextpdf.text.Anchor功能类似锚点、超链接
com.itextpdf.text.Chapter章节
com.itextpdf.text.Chunk能添加到文档里的最小文本块
com.itextpdf.text.Header这个信息不会显示到pdf,常常是编辑者自己定义的一些文档先关信息
com.itextpdf.text.Image图片
com.itextpdf.text.JpegJpeg的图片,其实它继承自Image
com.itextpdf.text.List列表,这里面放 ListItem
com.itextpdf.text.ListItem列表条目
com.itextpdf.text.Meta这个和Header类似,但这是固定的一些文档信息,字段名只允许:subject,title,keywords,author,creationdate,producer
com.itextpdf.text.Paragraph文本段落
com.itextpdf.text.Phrase文本,这就好像html里面的span,它可以设定自己的样式。

四、导出PDF

当你把你的各个数据全部写入到了 document 里面后,就可以将这个 document 导出给请求端了,如果我们把这个文档像这样进行构建写操作:

PdfWriter.getInstance(document, new FileOutputStream("D:/test.pdf"));

那么我们的pdf文件就会被保存到服务器里面,而我们的目标是导出给请求端,所以,只需要把 第二个参数从文件输出流变成响应输出流即可:

// ... 更多代码
PdfWriter.getInstance(document, response.getOutputStream());
// ... 跟多代码
Full text complete, Reproduction please indicate the source. Help you? Not as good as one:
Comment(Comments need to be logged in. You are not logged in.)
You need to log in before you can comment.

Comments (2 Comments)