截止2021年7月,itext的最新版本是itext7,本文是基于itext5编写(itext的大版本号是4-5-7,没有6)
itext5已于2020年9月停止维护
相关依赖:
<!-- https://mvnrepository.com/artifact/com.itextpdf/itextpdf -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.itextpdf/itext-asian -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
基本步骤
用itext生成pdf大体分为5个步骤:
os = response.getOutputStream();
// 1.建立Document对象的实例
Document doc = new Document();
// 2.建立一个书写器(Writer)与document对象关联,通过书写器可以将文件写到输出流中
PdfWriter.getInstance(doc, os);
// 3.打开文档
doc.open();
// 4.向文档中添加内容,这部分之后会详细说明
doc.add(new Paragraph("Hello World"));
// 5.关闭文档
doc.close();
重点在第4步打开文档之后往里面加东西的操作。
第2步生成了一个PdfWriter
存在了doc
里面,在第5步调用doc.close()
的时候调用这个PdfWriter
的close()
方法才关闭流,所以最好写成try-with-resource的形式保证流可以关闭。
文本
itext的文本由文本块(Chunk)、短语(Phrase)、段落(Paragraph)构成。
文本块(Chunk)是处理文本的最小单位,有一串带格式(包括字体、颜色、大小)的字符串组成。
如下代码就是创建一个字体为HELVETICA、大小为10、带下划线的字符串。
Font font = FontFactory.getFont(FontFactory.HELVETICA, 10, Font.UNDERLINE);
Chunk chunk = new Chunk("chunk underline", font);
短语(Phrase)由一个或多个文本块(Chunk)组成,短语(Phrase)也可以设定字体,但对于其中已设定过字体的文本块(Chunk)无效。通过短语(Phrase)函数add()
可以将一个文本块(Chunk)加到短语(Phrase)中。
如下代码就是创建一个包括"phrase"
和chunk
的短语,但是"phrase"
的字号是20,chunk
的字号是10。
Font font = FontFactory.getFont(FontFactory.HELVETICA, 20, Font.UNDERLINE);
Phrase phrase = new Phrase("phrase", font);
phrase.add(chunk);
段落(Paragraph)由一个或多个文本块(Chunk)或短语(Phrase)组成,相当于WORD中的段落,同样可以设定段落的字体大小、颜色等属性。另外也可以设定段落的首行缩进、对齐方式(左对齐、右对齐、居中对齐)。通过函数setAlignment可以设定段落的对齐方式,默认为左对齐。
Paragraph paragraph = new Paragraph("Hello World");
// 左对齐
paragraph.setAlignment(Element.ALIGN_LEFT);
// 居中
paragraph.setAlignment(Element.ALIGN_CENTER);
// 右对齐
paragraph.setAlignment(Element.ALIGN_RIGHT);
// 首行缩进10个单位,不清楚这个单位是什么,但肯定不是字符
paragraph.setFirstLineIndent(10);
中文处理
itext本身并不支持中文字体,如果把上面代码里的文字替换成中文将会输出空白文档(连换行都没有)。
使用中日韩文字需要引入亚洲字体包itext-asian
。
BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
Font font = new Font(baseFont, 12, Font.NORMAL);
上面这段代码表示生成宋体12号字,UniGB-UCS2-H
表示水平编码,UniGB-UCS2-V
则是垂直编码。
itext-asian
仅支持宋体一种简体字体,可通过扩展的方式添加其他字体。
图片
目前itext支持gif、jpeg、png、wmf等图片格式。获取Image的方法有2种,网络图片可以通过字节数组的方式,本地图片可以直接使用路径获取。都是调用静态函数Image.getInstance()
,利用Java多态的特性。
// 根据byte[]获取
byte[] b = bos.toByteArray();
Image image = Image.getInstance(b);
// 根据文件路径获取
String path = "/user/image.jpeg";
Image image = Image.getInstance(path);
表格
表格主要由table和cell两部分组成
table
// 表格有4列
PdfPTable table = new PdfPTable(4);
// 设置表格的宽度
table.setTotalWidth(600);
// 也可以每列分别设置宽度
table.setTotalWidth(new float[] { 160, 70, 130, 100 });
// 锁住宽度
table.setLockedWidth(true);
// 设置表格上面空白宽度
table.setSpacingBefore(30f);
// 设置表格下面空白宽度
table.setSpacingAfter(0f);
// 设置表格默认为无边框
table.getDefaultCell().setBorder(0);
doc.add(table);
图片 cell
byte[] bs = bos.toByteArray();
Image image = Image.getInstance(bs);
PdfPCell cell = new PdfPCell(image, true);
// 设置cell边框(无边框),或setBorder
cell.setBorderWidth(Rectangle.NO_BORDER);
// 设置cell高度
cell.setFixedHeight(100);
// 水平居中
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
// 垂直居中
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
table.addCell(cell);
在图片比较多的时候,也可使用下面的方法添加图片,这样可以省略一些重新设置格式的消耗,实测会比new一个cell稍微快一些。
PdfPCell cell = new PdfPCell();
cell.setFixedHeight(100);
cell.setImage(image1);
table.addCell(cell);
cell.setImage(image2);
table.addCell(cell);
文本 cell
上例cell中存放的是图片,图片高度会自适应。注意如果是文本,需要cell高度大于文字字体。比如cell高度是30,字体是14,则cell内可以写2行字,第一行放不下的字会自动到第二行。但如果字体是16,则只能放1行字,如果文本过长,长的那部分就不会显示。
PdfPCell cell = new PdfPCell(new Paragraph("Text cell"));
// 设置背景颜色
cell.setBackgroundColor(BaseColor.ORANGE);
// 设置边框颜色
cell.setBorderColor(BaseColor.GREEN);
// 设置左边距
cell.setPaddingLeft(10);
// 设置跨2行
cell.setRowspan(2);
// 设置跨两列
cell.setColspan(2);
table.addCell(cell);
二维码 cell
// 创建一个条形码对象
Barcode128 barcode128 = new Barcode128();
barcode128.setCode("123456789");
barcode128.setCodeType(Barcode128.CODE128);
// 生成条形码图片
Image image = barcode128.createImageWithBarcode(cb, null, null);
// 以图片的方式放到表格
PdfPCell cell = new PdfPCell(image, true);
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setFixedHeight(30);
table.addCell(cell);
最好给条形码设置一个合适的高度,否则黑条会过密。
todo
这篇文章需要补充的部分
- 如何导入自定义字体
- Image如何设置大小、透明度、自定义位置等参数
- 如何添加PDF文件信息
- 如何添加水印
- 如何添加页眉页脚
等有空就写......
2021年7月28日
参考
itextpdf生成表格的常见用法
https://blog.csdn.net/u010142437/article/details/84303581
[itext]Java生成PDF文件
https://www.cnblogs.com/qlqwjy/p/8213989.html
itextpdf JAVA 输出PDF文档