最近接手一个生成PDF授权书的需求,公司使用JDK8,于是还是先搜了搜使用JAVA语言如何操作授权书,经过筛选最终选择了IText,因为api比较通俗,并且社区还算活跃,下面则是对一些常用到的方法做了个总结(使用的是itext5的api)
Itext官方网址:https://itextpdf.com/en
准备工作:加依赖,我使用的是Itext5,推荐使用最新的itext7,新的功能更加丰富,有时间我会进行升级。
com.itextpdf
itext-asian
5.2.0
首先,对于授权书的生成有三个想法:
1.填充文本方式
授权书嘛,想想就是pdf中大部分数据内容都是相同的,可能就是每个用户的授权主体,授权时间,电话什么的不同,所以思路就是预先生成好授权书的源文件,就是将对于用户相同的内容先写好到授权书,然后将对于每个用户不用的数据预留出空间来进行内容的填充。但是比较麻烦的是需要定位的填充内容的位置,通过x,y的坐标定位填写内容的起始位置。
如上图,对于授权方相关的信息每个用户都是一样的,所以可以提前生成一个内容都写好的pdf文件,然后将被授权方需要填写的内容空出来,根据每个用户填写的不同信息分别填充不同的内容。代码:
// 读取pdf源文件
try(InputStream is = new FileInputStream(new File("C:\\Users\\Administrator\\Desktop\\source_v1.pdf"))){
// 设置字体样式 这种是使用自定义的字体,也可以使用默认的字体,但是默认字体格式太少,一般都是使用自定义的吧
BaseFont font = BaseFont.createFont("C:\\Users\\Administrator\\Desktop\\simkai.ttf",BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
// 替换文本
PdfReader reader = new PdfReader(is); // input PDF
PdfStamper stamper = new PdfStamper(reader,new FileOutputStream(new File("C:\\Users\\Administrator\\Desktop\\res.pdf"))); // output PDF
// 获取pdf文件第一页内容
PdfContentByte pageOne = stamper.getOverContent(1);
// 被授权方
setText(pageOne,410,580,"王大套",font,10);
//社会信用代码
setText(pageOne,410,559,"130xxxxxxxxxxxxxx0223",font,10);
// 电话
setText(pageOne,410,538,"131xxxx1234",font,10);
// 用户ID
setText(pageOne,410,517,"uid123_adskjflEMDK-dagjKJETD",font,10);
// 绘制
pageOne.fill();
// 关闭
stamper.flush();
stamper.close();
}catch (Exception e){
e.printStackTrace();
}
基本可以满足需求。
2.替换文本方式
这个也是个思路,但是没有使用,就是利用itext文本替换的功能,和方案1类似,将需要进行自定义填写的内容使用占位符,比如"被授权方:${the_auth_user}",然后用替换方式将字符串为"${the_auth_user}"替换成"王大套",也可以达到效果,这个大家可以试试,我也试过可以实现,但是没有使用。
3.从头生成
第三种就是如果每个用户的绝大部分内容都不相同呢,这样我们无法找个一个合适的文件作为源文件,所以干脆从头到尾生成一个pdf文件。
如上图,这是一般授权书的内容,有图片,有表格,有文字,示例代码:
String path = "C:\\Users\\Administrator\\Desktop\\";
// 设置字体样式
黑色字体
BaseFont bfChinese = BaseFont.createFont(path + "simkai.ttf",BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
Font blackFont = new Font(bfChinese);
blackFont.setSize(12);
blackFont.setStyle(FontFactory.HELVETICA);
blackFont.setColor(BaseColor.BLACK);
红色字体
Font redFont = new Font(bfChinese);
redFont.setSize(12);
redFont.setStyle(FontFactory.HELVETICA);
redFont.setColor(BaseColor.RED);
橙色字体
Font orangeFont = new Font(bfChinese);
orangeFont.setSize(12);
orangeFont.setStyle(FontFactory.HELVETICA);
orangeFont.setColor(BaseColor.ORANGE);
// 设置页面信息 A4纸,页边距
Document doc = new Document(PageSize.A4,90.14f,90.14f,72f,72f);
OutputStream out = new FileOutputStream(new File(path + "aaa.pdf"));
PdfWriter.getInstance(doc, out);
doc.open();
// 授权书标题
Paragraph title = new Paragraph("授权书(个人VIP)", blackFont);
title.setAlignment(Element.ALIGN_CENTER);
doc.add(title);
doc.add(new Paragraph("\n"));
// 设计信息表格
// 设置 3 列表格
PdfPTable table = new PdfPTable(3);
// 设置表格宽度
table.setTotalWidth(new float[]{20,40,40});// 这里是百分比,每列所占整个宽度的比例
table.setTotalWidth(414.992f);// 这是设置表格的定宽
table.setLockedWidth(true);// 这个必须设置为true,意思是按照我们设置的锁定表格的宽度
table.setHorizontalAlignment(Element.ALIGN_CENTER);
// 图片
Image cellimg = Image.getInstance(path + "thumb.png");
PdfPCell cell1 = new PdfPCell(cellimg, true);
cell1.setBorderColor(BaseColor.GRAY);// 单元格边框颜色
cell1.setPaddingLeft(10);
cell1.setFixedHeight(100);
cell1.setLeading(20,1);
cell1.setHorizontalAlignment(Element.ALIGN_CENTER);
cell1.setVerticalAlignment(Element.ALIGN_CENTER);
cell1.setRowspan(4);
cell1.setFixedHeight(50);
cell1.setTop(10);
table.addCell(cell1);
// 授权方
PdfPCell cell2 = new PdfPCell(new Paragraph("授权方:xxxxx",blackFont));
cell2.setBorderColor(BaseColor.GRAY);
cell2.setPaddingLeft(10);
cell2.setHorizontalAlignment(Element.ALIGN_LEFT);
cell2.setVerticalAlignment(Element.ALIGN_TOP);
table.addCell(cell2);
// 被授权方
PdfPCell cell3 = new PdfPCell();
Paragraph elements = new Paragraph();
elements.add(new Chunk("被授权方:王大套", blackFont));
cell3.setPhrase(elements);
cell3.setBorderColor(BaseColor.GRAY);
cell3.setPaddingLeft(10);
cell3.setHorizontalAlignment(Element.ALIGN_LEFT);
cell3.setVerticalAlignment(Element.ALIGN_TOP);
table.addCell(cell3);
// 授权方网站
PdfPCell cell4 = new PdfPCell(new Paragraph("授权⽅⽹站:xxxxx",blackFont));
cell4.setBorderColor(BaseColor.GRAY);
cell4.setPaddingLeft(10);
cell4.setHorizontalAlignment(Element.ALIGN_LEFT);
cell4.setVerticalAlignment(Element.ALIGN_TOP);
table.addCell(cell4);
// 身份证/统⼀社会信⽤代码:
PdfPCell cell5 = new PdfPCell(new Paragraph("身份证/统⼀社会信⽤代码:xxxxxx",blackFont));
cell5.setBorderColor(BaseColor.GRAY);
cell5.setPaddingLeft(10);
cell5.setHorizontalAlignment(Element.ALIGN_LEFT);
cell5.setVerticalAlignment(Element.ALIGN_TOP);
table.addCell(cell5);
// 地址
PdfPCell cell6 = new PdfPCell(new Paragraph("地址:xxxxxx",blackFont));
cell6.setBorderColor(BaseColor.GRAY);
cell6.setPaddingLeft(10);
cell6.setHorizontalAlignment(Element.ALIGN_LEFT);
cell6.setVerticalAlignment(Element.ALIGN_TOP);
table.addCell(cell6);
// 地址
PdfPCell cell7 = new PdfPCell(new Paragraph("地址:xxxxxxx",blackFont));
cell7.setBorderColor(BaseColor.GRAY);
cell7.setPaddingLeft(10);
cell7.setHorizontalAlignment(Element.ALIGN_LEFT);
cell7.setVerticalAlignment(Element.ALIGN_TOP);
table.addCell(cell7);
// 设计ID
PdfPCell cell8 = new PdfPCell();
Paragraph elements1 = new Paragraph();
elements1.add(new Chunk("内容id:", redFont));
elements1.add(new Chunk("sdfasd-DALKDA-dagfsadf", blackFont));
cell8.addElement(elements1);
cell8.setBorderColor(BaseColor.GRAY);
cell8.setPaddingLeft(10);
cell8.setHorizontalAlignment(Element.ALIGN_LEFT);
cell8.setVerticalAlignment(Element.ALIGN_TOP);
table.addCell(cell8);
// 联系电话
PdfPCell cell9 = new PdfPCell(new Paragraph("联系电话:xxxxxx",blackFont));
cell9.setBorderColor(BaseColor.GRAY);
cell9.setPaddingLeft(10);
cell9.setHorizontalAlignment(Element.ALIGN_LEFT);
cell9.setVerticalAlignment(Element.ALIGN_TOP);
table.addCell(cell9);
// 空白
PdfPCell cell10 = new PdfPCell(new Paragraph(" ",blackFont));
cell10.setBorderColor(BaseColor.GRAY);
cell10.setPaddingLeft(10);
cell10.setHorizontalAlignment(Element.ALIGN_LEFT);
cell10.setVerticalAlignment(Element.ALIGN_TOP);
table.addCell(cell10);
// 空白
PdfPCell cell11 = new PdfPCell(new Paragraph(" ",blackFont));
cell11.setBorderColor(BaseColor.GRAY);
cell11.setPaddingLeft(10);
cell11.setHorizontalAlignment(Element.ALIGN_CENTER);
cell11.setVerticalAlignment(Element.ALIGN_MIDDLE);
table.addCell(cell11);
// 被授权⽤户ID:
PdfPCell cell12 = new PdfPCell(new Paragraph("被授权⽤户ID:xxxxxx",blackFont));
cell12.setBorderColor(BaseColor.GRAY);
cell12.setPaddingLeft(10);
cell12.setHorizontalAlignment(Element.ALIGN_LEFT);
cell12.setVerticalAlignment(Element.ALIGN_TOP);
table.addCell(cell12);
doc.add(table);
doc.add(new Paragraph("\n"));
// 授权内容
Paragraph temp = new Paragraph("1.授权内容", blackFont);
temp.setLeading(23);
temp.setAlignment(Element.ALIGN_LEFT);
doc.add(temp);
temp = new Paragraph("xxxxxx", blackFont);
temp.setLeading(23);
temp.setAlignment(Element.ALIGN_LEFT);
doc.add(temp);
doc.add(new Paragraph("\n"));// 换行
temp = new Paragraph("2.授权范围", blackFont);
temp.setLeading(23);
temp.setAlignment(Element.ALIGN_LEFT);
doc.add(temp);
temp = new Paragraph("xxxxxx", blackFont);
temp.setLeading(23);
temp.setAlignment(Element.ALIGN_LEFT);
doc.add(temp);
doc.add(new Paragraph("\n"));// 换行
temp = new Paragraph("xxxxx公司", blackFont);
temp.setLeading(23);
temp.setAlignment(Element.ALIGN_RIGHT);
doc.add(temp);
temp = new Paragraph("2020 年 03 月 28 日", blackFont);
temp.setLeading(23);
temp.setAlignment(Element.ALIGN_RIGHT);
doc.add(temp);
doc.add(new Paragraph("\n"));// 换行
doc.close();
结果:
也是基本达到要求,当然都是伪代码,基本注释都写了,真正生产环境的代码需要进行整理、抽象和资源释放(各种流)等。
下次分享添加水印的几种方式