前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >iText的使用

iText的使用

作者头像
LeoXu
发布2018-08-15 14:31:29
2.2K0
发布2018-08-15 14:31:29
举报
文章被收录于专栏:LeoXu的博客LeoXu的博客

一、如何创建一个PDF文件,并向里面添加文字。

首先要getInstance并open一个Document对象,该对象也就代表了这个文件:

代码语言:javascript
复制
Document document = new Document(PageSize.A4);
PdfWriter.getInstance(
  document, new FileOutputStream(localFileFullPathName)
);
document.open();

然后就可以通过调用document对象的add来添加各种内容了:

代码语言:javascript
复制
document.add(table);

二、表格操作

表格是new出来的:

代码语言:javascript
复制
PdfPTable table = new PdfPTable(1);

带有一个入参的构造方法,这个参数表示表格的列数。这样构造出表格对象之后,就可以再构造出一个一个的PdfPCell单元格对象,然后逐个从左至右,从上至下逐个通过addCell方法添加到表格对象中:

代码语言:javascript
复制
PdfPCell cell3 = new PdfPCell();
cell3.setBorder(0);//不显示单元格的边框
Paragraph paragraph9 = new Paragraph("test");//Paragraph 是段落对象类
paragraph9.setSpacingBefore(12);
cell3.addElement(paragraph9);
table.addCell(cell3);

表格的列宽也可以调用方法来进行设置:

代码语言:javascript
复制
PdfPTable table = new PdfPTable(3);
table.setLockedWidth(true);
table.setWidthPercentage(100);
float[] columnWidths = {177,176,176};//采用点数制单位
table.setTotalWidth(columnWidths);

还有各种样式的调整方法,可参考iText的API文档。

三、点数制单位(参考了百度知道)

1点(pt)=1/72(英寸)inch 1英寸=25.4毫米mm搜索

pt全称为point,但中文不叫“点”,查英语字典可以看到,确切的说法是一个专用的印刷单位“磅”,大小为1/72英寸。所以它是一个自然界标准的长度单位,也称为“绝对长度”。

1in = 2.54cm = 25.4 mm = 72pt = 6pc

因此就有这样的说法,在网页设计中,pixel是相对大小,而point是绝对大小。

中文字号制与点数制的对照关系:{macro}{Chinese Font Size} 。1770年法国人狄道(F.A.Didot)制定点数制,规定1法寸为72点,即:1点=0.3759毫米。狄道点数制在法国、德国、奥地利、比利时、丹麦、匈牙利等国比较流行。1886年全美活字铸造协会以派卡(pica)为基准制定派卡点数制,规定1pica=12point(点),即:fbox{1点=0.013837英寸=0.35146毫米} 20世纪初派卡点数制传入我国,并得到逐步推广。在实用中对常用点数以号数命名而产生了号数制,二者换算如下(以pt代表“点”):

初号= 42pt;小初号= 36pt;一号= 28pt;二号= 21pt;小二号= 18pt;三号= 15.75pt;四号= 14pt;

小四号= 12pt;五号= 10.5pt;小五号= 9pt;六号= 7.875pt;七号= 5.25pt。

四、如何添加图片

iText的jar包里面有一个Image类。

可以通过图片文件的BASE64字符串来生成Image对象实例,然后添加到pdf文档或者文档的子要素中:

代码语言:javascript
复制
String imageBase64Data = Base64DataUtils.getData(imageDataKeyName);
Image image = Image.getInstance(Base64.decodeBase64(imageBase64Data.getBytes()));
image.scaleToFit(140F, 70F);
PdfPCell cell = new PdfPCell(image, false);
cell.setBorder(0);
//TODO ...

除了上面的代码所提供的方式,还有直接添加到PDF文档Document对象上:

代码语言:javascript
复制
Image image = Image.getInstance(Base64.decodeBase64(imageBase64Data.getBytes()));
image.setAbsolutePosition(400, 30);//以左下角作为原点的坐标平面上的绝对位置
image.scaleToFit(150, 150);//相对尺寸范围,图片会缩放成这个范围内的最大尺寸
document.add(image);

使用PdfStamper对象操作pdf文件模板来生成文档时,还以从PdfStamper对象获取到代表某一页上覆盖内容的PdfContentByte对象,之后就可以在这个对象上调用addImage方法来添加图片了:

代码语言:javascript
复制
PdfReader reader = new PdfReader(TEMPLATE_FILE_FULL_PATH);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
PdfStamper ps = new PdfStamper(reader, bos);
PdfContentByte overContent = ps.getOverContent(8);
//...
Image image = Image.getInstance(Base64.decodeBase64(imageBase64Data.getBytes()));
image.setAbsolutePosition(posX, posY);
image.scaleToFit(scaleFitW, scaleFitH);
overContent.addImage(image);

五、处理中文字体

很多同学都在向文档中添加含有中文内容的要素时遇到问题,只要是中文(其实还有其他很多字符都会有这个情况,中文只是其中一个子集)的地方就显示空白。一般是缺少字体库造成的,说得明白点,就是程序找不到对这个文字的定义,所以就显示。

网上搜索一般说只要添加一个itextasia.jar到classpath就能轻松解决,但是我发现对于初学者这样做并不轻松,倒不如找一个字符定义全的字体文件(ttf格式的)引入来得保险,不过这样做的话,通常会要在代码中加载一个几M到几十M不等的ttf文件,不知道iText对这样的操作有没有做性能优化了。

代码如下:

代码语言:javascript
复制
BaseFont bfFangSong = BaseFont.createFont(
		"fonts/SIMFANG.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED
), bf;//这里ttf就跟代码放到一起
bf = bfFangSong;
Font font1 = new Font(bf, 10);//字体大小
Paragraph paragraph1 = new Paragraph("中文字符", font1);
PdfPCell cell1 = new PdfPCell();
cell1.setBorder(0);
cell1.addElement(paragraph1);
PdfPTable table = new PdfPTable(1);
table.setWidthPercentage(100);
table.addCell(cell1);

只要ttf文件里面对字符的定义全的话,基本上就不会出什么问题了。

六、通过模板来生成文档

首先需要有一个模板,也是pdf格式的,里面会有可输入的表单元素,这样的元素可以通过在利用Adobe Acrobat编辑PDF模板文件时加入。

每个表单元素都会添加名称,这样在代码中就可以通过这个名称来向生成的PDF文件中插值,实现通过模板来生成文档。

有了模板之后,就可以生成利用PdfReader来生成PdfStamper对象,对模板进行各种操作(如插值还有添加额外的一些内容),最后导出新的PDF文件。

代码如下:

代码语言:javascript
复制
//通过 PdfReader 和 ByteArrayOutputStream 来生成 PdfStamper 实例
PdfReader reader = new PdfReader(TEMPLATE_FILE_FULL_PATH);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
PdfStamper ps = new PdfStamper(reader, bos);
//获取到所有的表单域
AcroFields s = ps.getAcroFields();
//也可以设置表单域的字体
BaseFont bfFangSong = BaseFont.createFont(
		FONT_FANG_SONG, BaseFont.IDENTITY_H, BaseFont.EMBEDDED
), bf;
bf = bfFangSong;
ArrayList<BaseFont> fontList = new ArrayList<BaseFont>();
fontList.add(bf);
s.setSubstitutionFonts(fontList);
//插值
Map<String, Item> fieldsMap = s.getFields();
Set<String> keySet = fieldsMap.keySet();
for (String key : keySet) {
	s.setField(key, filedValues.getString(key, ""));
}
ps.setFormFlattening(true);
//导出
	ps.close();
try {
	fos = new FileOutputStream(saveFileFullPath);
	fos.write(bos.toByteArray());
    fos.flush();
} catch (Exception e) {
	e.printStackTrace();
	throw e;
} finally {
	if (null != fos) {
		fos.close();
	}
}

额外内容,比如图片,可以通过第四节介绍的方法来添加。

七、拼接pdf文档

有时也会有这样的需求,就是将两个或者多个pdf文件合并到一起生成一个新的pdf文件,这里有一个从网上copy的代码可以直接拿来用,经测试有效。

代码语言:javascript
复制
package com.ailk.server.util;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.itextpdf.text.Document;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfWriter;
/**
 * pdf文件拼接工具 2017-01-10
 *
 */
public class iTextPdfConcatUtils {
	/**
	 * 拼接多个pdf文件
	 * 
	 * @param path1
	 * @param path2
	 */
	public static void concatPDFs(
			List<InputStream> streamOfPDFFiles,
			OutputStream outputStream, 
			boolean paginate
	) {
		Document document = new Document();
		try {
			List<InputStream> pdfs = streamOfPDFFiles;
			List<PdfReader> readers = new ArrayList<PdfReader>();
			int totalPages = 0;
			Iterator<InputStream> iteratorPDFs = pdfs.iterator();
			// Create Readers for the pdfs.
			while (iteratorPDFs.hasNext()) {
				InputStream pdf = iteratorPDFs.next();
				PdfReader pdfReader = new PdfReader(pdf);
				readers.add(pdfReader);
				totalPages += pdfReader.getNumberOfPages();
			}
			// Create a writer for the outputstream
			PdfWriter writer = PdfWriter.getInstance(document, outputStream);
			document.open();
			BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA,
					BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
			PdfContentByte cb = writer.getDirectContent(); // Holds the PDF
			// data
			PdfImportedPage page;
			int currentPageNumber = 0;
			int pageOfCurrentReaderPDF = 0;
			Iterator<PdfReader> iteratorPDFReader = readers.iterator();
			// Loop through the PDF files and add to the output.
			while (iteratorPDFReader.hasNext()) {
				PdfReader pdfReader = iteratorPDFReader.next();
				// Create a new page in the target for each source page.
				while (pageOfCurrentReaderPDF < pdfReader.getNumberOfPages()) {
					document.newPage();
					pageOfCurrentReaderPDF++;
					currentPageNumber++;
					page = writer.getImportedPage(pdfReader,
							pageOfCurrentReaderPDF);
					cb.addTemplate(page, 0, 0);
					// Code for pagination.
					if (paginate) {
						cb.beginText();
						cb.setFontAndSize(bf, 9);
						cb.showTextAligned(PdfContentByte.ALIGN_CENTER, ""
								+ currentPageNumber + " of " + totalPages, 520,
								5, 0);
						cb.endText();
					}
				}
				pageOfCurrentReaderPDF = 0;
			}
			outputStream.flush();
			document.close();
			outputStream.close();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (document.isOpen())
				document.close();
			try {
				if (outputStream != null)
					outputStream.close();
			} catch (IOException ioe) {
				ioe.printStackTrace();
			}
		}
	}
	public static void main(String[] args) throws Exception {
		List<InputStream> streamOfPDFFiles = new ArrayList<InputStream>();
		streamOfPDFFiles.add(new FileInputStream("D:\\temp\\fileCache\\demo-1.pdf"));
		streamOfPDFFiles.add(new FileInputStream("D:\\temp\\fileCache\\demo-2.pdf"));
		OutputStream outputStream = new FileOutputStream(
				"D:\\temp\\" + System.currentTimeMillis() + ".pdf"
		);
		iTextPdfConcatUtils.concatPDFs(streamOfPDFFiles, outputStream , false);
	}
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017/02/10 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档