pdf填充
GitHub[itexpdf] https://github.com/itext/itextpdf
第一步:编辑模板
使用可以编辑表单的pdf编辑器编辑pdf表单,效果如下。(我用的是迅捷pdf编辑器。)
第二步:使用iTextPdf设置表单属性值,支持多种类型,可自主研究
简单代码记录如下:
①导入以下两个包(代码中也使用到了Hutools,看个人情况):
依赖jar包
<!-- https://mvnrepository.com/artifact/com.itextpdf/itextpdf -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.itextpdf/itext-asian -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.10</version>
</dependency>
②核心逻辑实现
设置pdf表单属性值
package fill;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Map;
public class PdfUtils {
/**
* Description: 使用map中的参数填充pdf,map中的key和pdf表单中的field对应 <br>
* @Param fieldValueMap:文件字段 file:源文件的字节流 contractFileName:生成目标文件存放的地址
* @return
*/
public static void fillParam(Map<String, String> fieldValueMap, byte[] file, String contractFileName) throws IOException {
if (fieldValueMap == null) {
return;
}
FileOutputStream fos = null;
try {
//生成pdf 的路径
fos = new FileOutputStream(contractFileName);
PdfReader reader = null;
PdfStamper stamper = null;
BaseFont base;
try {
reader = new PdfReader(file);
stamper = new PdfStamper(reader, fos);
stamper.setFormFlattening(true);
// 设置自定义字体,不然中文不显示
base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
AcroFields acroFields = stamper.getAcroFields();
for (String key : acroFields.getFields().keySet()) {
//将map填充到对应的位置中
if (!fieldValueMap.containsKey(key)) {
continue;
}
int fieldType = acroFields.getFieldType(key);
if (AcroFields.FIELD_TYPE_TEXT == fieldType) {
//设置一些填充位置的字体属性
acroFields.setFieldProperty(key, "textfont", base, null);
acroFields.setFieldProperty(key, "textsize", new Float(9), null);
acroFields.setField(key, fieldValueMap.get(key), true);
} else if (AcroFields.FIELD_TYPE_CHECKBOX == fieldType || AcroFields.FIELD_TYPE_RADIOBUTTON == fieldType ) {
//复选框、单选框
acroFields.setField(key, "Yes".equals(fieldValueMap.get(key)) ? "Yes" : "No", true);
} else if (AcroFields.FIELD_TYPE_PUSHBUTTON == fieldType) {
//图片
int pageNo = acroFields.getFieldPositions(key).get(0).page;
Rectangle signRect = acroFields.getFieldPositions(key).get(0).position;
float x = signRect.getLeft();
float y = signRect.getBottom();
Image image = Image.getInstance(fieldValueMap.get(key));
PdfContentByte overContent = stamper.getOverContent(pageNo);
image.scaleToFit(signRect.getWidth(), signRect.getHeight());
image.setAbsolutePosition(x, y);
overContent.addImage(image);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (stamper != null) {
try {
stamper.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (reader != null) {
reader.close();
}
}
} catch (Exception e) {
System.out.println("填充参数异常");
e.printStackTrace();
} finally {
fos.close();
}
}
}
③测试类
点击查看代码
package fill;
import cn.hutool.core.io.FileUtil;
import com.itextpdf.text.Document;
import com.itextpdf.text.pdf.PdfCopy;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfReader;
import java.io.*;
import java.util.HashMap;
import java.util.Set;
import java.util.TreeSet;
public class PdfFillTest2 {
public static void main(String[] args) throws IOException {
HashMap<String, String> map = new HashMap<>();
map.put("custName", "你叫什么名字啊?");
map.put("certType", "100");
map.put("certNo", "123345463572345473562");
map.put("field1", "xxx开户行");
map.put("field2", "654321xxxxxxxx1");
map.put("field3", "xxx开户行");
map.put("field4", "654321xxxxxxxx1");
map.put("l1", "Yes");
map.put("l3", "Yes");
map.put("l4", "Yes");
map.put("image", "D:\\pdf\\文件.png");
//源模板地址
String sourceFile = "D:\\pdf\\form.pdf";
//生成文件的目标地址
String targetFile = "D:\\pdf\\form_out.pdf";
File templateFile = new File(sourceFile);
try {
/* 获取模板文件中的所有表单域
Set<String> templateFileFieldNames = PdfUtils.getTemplateFileFieldNames(sourceFile);
System.out.println(templateFileFieldNames);*/
// PdfUtils.fillParam(map, FileUtils.readFileToByteArray(templateFile), targetFile);
PdfUtils.fillParam(map, FileUtil.readBytes(templateFile), targetFile);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Description: 获取pdf表单中的fieldNames<br>
* @author mk
* @Date 2018-11-2 15:21 <br>
* @Param
* @return
*/
public static Set<String> getTemplateFileFieldNames(String pdfFileName) {
Set<String> fieldNames = new TreeSet<String>();
PdfReader reader = null;
try {
reader = new PdfReader(pdfFileName);
Set<String> keys = reader.getAcroFields().getFields().keySet();
for (String key : keys) {
int lastIndexOf = key.lastIndexOf(".");
int lastIndexOf2 = key.lastIndexOf("[");
fieldNames.add(key.substring(lastIndexOf != -1 ? lastIndexOf + 1 : 0, lastIndexOf2 != -1 ? lastIndexOf2 : key.length()));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
reader.close();
}
}
return fieldNames;
}
/**
* Description: 读取文件数组<br>
* @author mk
* @Date 2018-11-2 15:21 <br>
* @Param
* @return
*/
public static byte[] fileBuff(String filePath) throws IOException {
File file = new File(filePath);
long fileSize = file.length();
if (fileSize > Integer.MAX_VALUE) {
//System.out.println("file too big...");
return null;
}
FileInputStream fi = new FileInputStream(file);
byte[] file_buff = new byte[(int) fileSize];
int offset = 0;
int numRead = 0;
while (offset < file_buff.length && (numRead = fi.read(file_buff, offset, file_buff.length - offset)) >= 0) {
offset += numRead;
}
// 确保所有数据均被读取
if (offset != file_buff.length) {
throw new IOException("Could not completely read file " + file.getName());
}
fi.close();
return file_buff;
}
/**
* Description: 合并pdf <br>
* @author mk
* @Date 2018-11-2 15:21 <br>
* @Param
* @return
*/
public static void mergePdfFiles(String[] files, String savepath) {
Document document = null;
try {
document = new Document(); //默认A4大小
PdfCopy copy = new PdfCopy(document, new FileOutputStream(savepath));
document.open();
for (int i = 0; i < files.length; i++) {
PdfReader reader = null;
try {
reader = new PdfReader(files[i]);
int n = reader.getNumberOfPages();
for (int j = 1; j <= n; j++) {
document.newPage();
PdfImportedPage page = copy.getImportedPage(reader, j);
copy.addPage(page);
}
} finally {
if (reader != null) {
reader.close();
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭PDF文档流,OutputStream文件输出流也将在PDF文档流关闭方法内部关闭
if (document != null) {
document.close();
}
}
}
}
④效果图
There are two things to do in a day: a happy thing and a difficult one.