一、如何创建一个PDF文件,并向里面添加文字。
首先要getInstance并open一个Document对象,该对象也就代表了这个文件:
Document document = new Document(PageSize.A4);
PdfWriter.getInstance(
document, new FileOutputStream(localFileFullPathName)
);
document.open();
然后就可以通过调用document对象的add来添加各种内容了:
document.add(table);
二、表格操作
表格是new出来的:
PdfPTable table = new PdfPTable(1);
带有一个入参的构造方法,这个参数表示表格的列数。这样构造出表格对象之后,就可以再构造出一个一个的PdfPCell单元格对象,然后逐个从左至右,从上至下逐个通过addCell方法添加到表格对象中:
PdfPCell cell3 = new PdfPCell();
cell3.setBorder(0);//不显示单元格的边框
Paragraph paragraph9 = new Paragraph("test");//Paragraph 是段落对象类
paragraph9.setSpacingBefore(12);
cell3.addElement(paragraph9);
table.addCell(cell3);
表格的列宽也可以调用方法来进行设置:
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文档或者文档的子要素中:
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对象上:
Image image = Image.getInstance(Base64.decodeBase64(imageBase64Data.getBytes()));
image.setAbsolutePosition(400, 30);//以左下角作为原点的坐标平面上的绝对位置
image.scaleToFit(150, 150);//相对尺寸范围,图片会缩放成这个范围内的最大尺寸
document.add(image);
使用PdfStamper对象操作pdf文件模板来生成文档时,还以从PdfStamper对象获取到代表某一页上覆盖内容的PdfContentByte对象,之后就可以在这个对象上调用addImage方法来添加图片了:
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对这样的操作有没有做性能优化了。
代码如下:
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文件。
代码如下:
//通过 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的代码可以直接拿来用,经测试有效。
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);
}
}
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有