遇到的问题
1.addSubstitutionFont 设置字体填充不生效,以及生成的pdf文件过大
解决:删除itext-asian 包引用
2.BaseFont无法设置粗体
解决:用getFieldPositions 加载文本框 通过Font类来设置粗体.
3.文本框设置粗体大号文字产生位移
解决:自己调整new Paragraph 的几个参数控制.
pom必须引入
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.4.3</version>
</dependency>
<dependency>
<groupId>com.itextpdf.tool</groupId>
<artifactId>xmlworker</artifactId>
<version>5.4.1</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.0</version>
</dependency>
通用生成示例
package com.example.pdftmpelet;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import java.io.*;
import java.util.List;
/**
* 使用pdf模板生成pdf文件
*/
public class WriteToPDF {
public static String create(String mobanPath,String fileName,String textFields,String imgFields) {
JSONArray text=JSONArray.parseArray(textFields);
JSONArray img=JSONArray.parseArray(imgFields);
File f=new File("D:\\"+fileName+System.currentTimeMillis()+".pdf");
OutputStream os = null;
PdfStamper ps = null;
PdfReader reader = null;
try {
// 1 获取文件的输出流
os = new FileOutputStream(f);
// 2 读取pdf模板
reader = new PdfReader(mobanPath);
// 3 根据表单生成一个新的pdf
ps = new PdfStamper(reader, os);
// 4 获取pdf表单
AcroFields form = ps.getAcroFields();
ps.setFormFlattening(true);
// 拼接字体文件的完整路径
// 5 给表单添加中文字体
BaseFont font = BaseFont.createFont("C:/Windows/Fonts/simsun.ttc,0", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
font.setSubset(true);
form.addSubstitutionFont(font);
// 6遍历data赋值到form
if(text!=null && text.size()>0){
for (int i = 0; i < text.size(); i++) {
JSONObject o = text.getJSONObject(i);
String key=o.getString("KEY");
String value=o.getString("VALUE");
String fontsize=o.getString("SIZE");
String ifBlod=o.getString("BLOD");
Float sze=12f;
try {
sze=fontsize==null?sze:Float.parseFloat(fontsize);
}catch (Exception e){
System.out.println("font size error!"+fontsize);
}
//如果是加粗就使用 Rectangle 写入, 这里有个坑, 字号过大会跑出去. 可以自己调整new Rectangle 的几个值来兼容.
if("Y".equals(ifBlod)){
int tpdd=sze.intValue()-12-2;
Font blod = new Font(font, sze, Font.BOLD);
List<AcroFields.FieldPosition> multiLinePosition = form.getFieldPositions(key);
int page = multiLinePosition.get(0).page;
Rectangle rectangle = multiLinePosition.get(0).position;
float left = rectangle.getLeft();
float right = rectangle.getRight();
float top = rectangle.getTop();
float bottom = rectangle.getBottom();
PdfContentByte pdfContentByte = ps.getOverContent(page);
ColumnText columnText = new ColumnText(pdfContentByte);
Rectangle r = new Rectangle(left, bottom, right, top-(tpdd>0?tpdd:0));
columnText.setSimpleColumn(r);
Chunk chunk = new Chunk(value);
Paragraph paragraph = new Paragraph(12, chunk);
columnText.addText(paragraph);
paragraph.setFont(blod);
columnText.addElement(paragraph);
columnText.go();
}else{
form.setFieldProperty(key, "textsize", sze, null);
form.setFieldProperty(key, "spacing", 1f, null);
form.setField(key, value);
}
}
}
// 7 填充图片到form
PdfStamper stamper = ps;
if(img!=null && img.size()>0){
for (int i = 0; i < img.size(); i++) {
JSONObject o = img.getJSONObject(i);
String key=o.getString("KEY");
String value=o.getString("VALUE");
try {
List<AcroFields.FieldPosition> fieldPositions = form.getFieldPositions(key);
for (AcroFields.FieldPosition fieldPosition : fieldPositions) {
// 通过域名获取所在页和坐标,左下角为起点
int pageno = fieldPosition.page;
Rectangle signrect = fieldPosition.position;
float x = signrect.getLeft();
float width = signrect.getWidth();
float y = signrect.getBottom();
// 读图片
Image image = Image.getInstance(value);
float img_width = image.getWidth();
// 获取操作的页面
PdfContentByte under = stamper.getOverContent(pageno);
// 图片的大小
image.scaleToFit(signrect.getWidth(), signrect.getHeight());
// 添加图片
image.setAbsolutePosition(x, y);
under.addImage(image);
}
} catch (BadElementException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (DocumentException e) {
e.printStackTrace();
}
}
}
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
try {
ps.close();
reader.close();
os.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return f.getAbsolutePath();
}
public static void main(String[] args) {
String text="[{\"KEY\":\"文本域名称\",\"VALUE\":\"填充值\",\"SIZE\":\"20\",\"BLOD\":\"Y\"},{\"KEY\":\"文本域名称\",\"VALUE\":\"123123\"},{\"KEY\":\"文本域名称\",\"VALUE\":\"123123\",\"BLOD\":\"Y\"},{\"KEY\":\"文本域名称\",\"VALUE\":\"123456\"}]";
String img="[{\"KEY\":\"图片渲染\",\"VALUE\":\"本地图片绝对路径或者网络图片url\"}]";
//生成pdf文件 通过json指定一堆待填充 的文本域名称, 值, 字号, 是否加粗
String rsp=create("D:\\moban.pdf","测试1",text,img);
System.out.println(rsp);
}
}