itextpdf 根据pdf表单模板填充生成pdf
模板创建
示例:使用adobe acrobat工具创建模板
以excel生成表单模板为例
1、创建表单excel

2、新建PDF表单模板
打开pdf工具:文件->创建->创建表单


选择创建的excel导入

编辑导入的表单
导入后左侧为字段名,右侧为表单字段内容,即表单占位,可双击进行编辑
名称即为itext读取时获取到的key

依赖jar包
<dependency>
<groupId>com.itextpdfgroupId>
<artifactId>itextpdfartifactId>
<version>5.5.13version>
dependency>
<dependency>
<groupId>cn.hutoolgroupId>
<artifactId>hutool-allartifactId>
<version>5.3.5version>
dependency>
实现代码
表单pdf字段配置信息实体类
import com.itextpdf.text.pdf.BaseFont;
import com.test.utils.pdf.PdfCreateUtil;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Optional;
@Data
@ApiModel("表单pdf字段配置信息")
public class FormPdfFieldConfig {
@ApiModelProperty("字体大小,默认14")
private float fontSize = 14f;
@ApiModelProperty("字体样式")
private BaseFont baseFont;
@ApiModelProperty("单元格内段落行间距,默认1.5倍")
private float cellLineLeading = 1.5f;
@ApiModelProperty("图片位置x轴坐标")
private float xPos = -1f;
@ApiModelProperty("图片位置y轴坐标")
private float yPos = -1f;
@ApiModelProperty("图片宽度")
private float width = -1f;
@ApiModelProperty("图片高度")
private float height = -1f;
public BaseFont getBaseFont() {
baseFont = Optional.ofNullable(baseFont).orElse(PdfCreateUtil.getDefaultBaseFont());
return baseFont;
}
}
表单pdf参数信息实体类
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Optional;
@Data
@ApiModel("表单pdf参数信息")
public class FormPdfParamInfo {
@ApiModelProperty("字段填充类型-自适应文本填充")
public static final String FIELD_FILL_TYPE_ADAPTIVE = "adaptive";
@ApiModelProperty("字段填充类型-二维码填充")
public static final String FIELD_FILL_TYPE_QR_IMAGE = "qrImage";
@ApiModelProperty("字段key")
private String fieldKey;
@ApiModelProperty("字符串字段值")
private String stringValue;
@ApiModelProperty("图片内容")
private String imageContent;
@ApiModelProperty("字段填充类型")
private String fieldFillType = FIELD_FILL_TYPE_ADAPTIVE;
@ApiModelProperty("字段配置信息")
private FormPdfFieldConfig fieldConfig;
@ApiModelProperty("字段所在pdf页码,从1开始")
private int pageNum = 1;
public FormPdfFieldConfig getFieldConfig() {
fieldConfig = Optional.ofNullable(fieldConfig).orElse(new FormPdfFieldConfig());
return fieldConfig;
}
}
表单类型pdf字段处理工具类
import cn.hutool.extra.qrcode.QrCodeUtil;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.test.constants.NumberConst;
import com.test.vo.pdf.FormPdfFieldConfig;
import com.test.vo.pdf.FormPdfParamInfo;
import java.awt.image.BufferedImage;
import java.io.IOException;
public class PdfFormFieldUtil {
public static void setAdaptiveField(AcroFields acroFields, PdfContentByte pdfContentByte, FormPdfParamInfo paramInfo) {
PdfPTable pdfPtable = new PdfPTable(NumberConst.NUM_1);
Rectangle rectangle = acroFields.getFieldPositions(paramInfo.getFieldKey()).get(NumberConst.NUM_0).position;
float totalWidth = rectangle.getRight() - rectangle.getLeft() - 1;
pdfPtable.setTotalWidth(totalWidth);
getTable(pdfPtable, rectangle, paramInfo);
pdfPtable.writeSelectedRows(0, -1, rectangle.getLeft(), rectangle.getTop(), pdfContentByte);
}
public static void setQrImage(AcroFields acroFields, PdfContentByte pdfContentByte, FormPdfParamInfo paramInfo) throws DocumentException, IOException {
Rectangle rectangle = acroFields.getFieldPositions(paramInfo.getFieldKey()).get(NumberConst.NUM_0).position;
FormPdfFieldConfig fieldConfig = paramInfo.getFieldConfig();
BufferedImage bufImg = QrCodeUtil.generate(paramInfo.getImageContent(), 400, 400);
Image image = Image.getInstance(bufImg, null);
float x = fieldConfig.getXPos()>0 ? fieldConfig.getXPos() : rectangle.getLeft();
float y = fieldConfig.getYPos()>0 ? fieldConfig.getYPos() : rectangle.getBottom();
image.setAbsolutePosition(x, y);
float width = fieldConfig.getWidth()>0 ? fieldConfig.getWidth() : rectangle.getWidth();
float height = fieldConfig.getHeight()>0 ? fieldConfig.getHeight() : rectangle.getHeight();
image.scaleToFit(width, height);
pdfContentByte.addImage(image);
}
private static void getTable(PdfPTable table, Rectangle rectangle, FormPdfParamInfo paramInfo) {
FormPdfFieldConfig fieldConfig = paramInfo.getFieldConfig();
Font cellTitleFont = new Font(fieldConfig.getBaseFont(), fieldConfig.getFontSize(), Font.NORMAL);
Paragraph titleTitle = new Paragraph(paramInfo.getStringValue(),cellTitleFont);
PdfPCell cell = new PdfPCell(titleTitle);
cell.setBorderWidth(0);
cell.setPaddingTop(-5f);
cell.setLeading(0f, fieldConfig.getCellLineLeading());
table.addCell(cell);
float i = 0.5f;
float j = 0.1f;
if(table.getTotalHeight()>rectangle.getHeight()){
table.deleteBodyRows();
fieldConfig.setFontSize(fieldConfig.getFontSize()-i);
fieldConfig.setCellLineLeading(fieldConfig.getCellLineLeading()-j);
getTable(table, rectangle, paramInfo);
}
}
}
pdf生成工具类
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Map;
import java.util.Optional;
@Slf4j
public class PdfCreateUtil {
private static BaseFont DEFAULT_BASE_FONT = null;
public static byte[] createPdfByFormTemplate(Map<String, FormPdfParamInfo> paramMap, PdfFileConfig fileConfig) {
try {
String basePath = PdfCreateUtil.class.getClassLoader().getResource("").getFile();
BaseFont baseFont = BaseFont.createFont(basePath + Optional.ofNullable(fileConfig.getFontFilePath()).orElse("fontfiles/song.ttf"), BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
DEFAULT_BASE_FONT = baseFont;
ArrayList<BaseFont> fontList = new ArrayList<BaseFont>();
fontList.add(baseFont);
PdfReader pdfReader = new PdfReader(basePath + fileConfig.getPdfTempPath());
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
PdfStamper pdfStamper = new PdfStamper(pdfReader, outputStream);
AcroFields acroFields = pdfStamper.getAcroFields();
acroFields.setSubstitutionFonts(fontList);
Map<String, AcroFields.Item> fieldMap = acroFields.getFields();
for (String fieldKey : fieldMap.keySet()) {
FormPdfParamInfo paramInfo = paramMap.get(fieldKey);
if (paramInfo != null){
switch (paramInfo.getFieldFillType()){
case FormPdfParamInfo.FIELD_FILL_TYPE_QR_IMAGE:
PdfFormFieldUtil.setQrImage(acroFields, pdfStamper.getOverContent(paramInfo.getPageNum()), paramInfo);
break;
default:
PdfFormFieldUtil.setAdaptiveField(acroFields, pdfStamper.getOverContent(paramInfo.getPageNum()), paramInfo);
}
}
}
pdfStamper.setFormFlattening(true);
pdfStamper.close();
pdfReader.close();
outputStream.close();
return outputStream.toByteArray();
} catch (Exception e) {
log.error("pdf生成异常", e);
}
return null;
}
public static BaseFont getDefaultBaseFont() {
return DEFAULT_BASE_FONT;
}
}
使用示例(数据组装)
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.test.constant.BusiConstant;
import com.test.constants.NumberConst;
import com.test.utils.pdf.PdfCreateUtil;
import com.test.vo.pdf.FormPdfParamInfo;
import com.test.vo.pdf.PdfFileConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
public byte[] createPdfByTemplate(String type, JSONObject paramJson) {
Map<String, FormPdfParamInfo> paramMap = new HashMap<>(NumberConst.NUM_4);
PdfFileConfig fileConfig = new PdfFileConfig();
if (StringUtils.isBlank(type)){
log.error("类型参数为空");
return null;
}
if (OtherbusiConstant.ENTERPRISE_TYPE_ENTERPRISE.equals(type)){
fileConfig.setPdfTempPath("pdftemplate/template1.pdf");
} else if (OtherbusiConstant.ENTERPRISE_TYPE_INDIVIDUAL.equals(type)){
fileConfig.setPdfTempPath("pdftemplate/template2.pdf");
}
if (paramJson == null || paramJson.isEmpty()){
log.error("pdf生成参数数据为空,type=", type);
return null;
}
paramJson.entrySet().forEach( entry -> {
FormPdfParamInfo paramInfo = new FormPdfParamInfo();
paramInfo.setFieldKey(entry.getKey());
paramInfo.setStringValue((String) Optional.ofNullable(entry.getValue()).orElse(""));
if (BusiConstant.TYPE_FIRST.equals(type)){
if (BusiConstant.TYPE_SECOND.contains(entry.getKey())){
paramInfo.setPageNum(NumberConst.NUM_2);
}
}
paramMap.put(entry.getKey(), paramInfo);
});
return PdfCreateUtil.createPdfByFormTemplate(paramMap, fileConfig);
}