使用java通过pdf 模板动态填充数据
1、准备pdf 模板文件
使用表单对pdf 文件进行编辑,
黑色框框是表单域,即java 代码中使用map的key ,通过key 将map中key 对应的value填充到表单中
2、java 代码
工具类
package com.creditease.collection.common.utils;
import com.itextpdf.text.Document;
import com.itextpdf.text.pdf.*;
import org.apache.commons.io.IOUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
/**
* pdf 处理工具类:用于填充pdf 模板数据使用
* * 依赖的包:itextpdf itext-asian
* * commons-io,commons-codec
*/
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) {
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()) {
//设置一些填充位置的字体属性
acroFields.setFieldProperty(key, "textfont", base, null);
acroFields.setFieldProperty(key, "textsize", new Float(9), null);
}
if (fieldValueMap != null) {
//将map填充到对应的位置中
for (String fieldName : fieldValueMap.keySet()) {
acroFields.setField(fieldName, fieldValueMap.get(fieldName));
}
}
} 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 {
IOUtils.closeQuietly(fos);
}
}
/**
* 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();
}
}
}
}
测试类
package com.creditease.collection.service.YRDEvidence;
import com.creditease.collection.common.utils.PdfUtils;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
public class TestPdf {
public static void main(String[] args) {
HashMap map = new HashMap<String, String>();
map.put("name", "杨杰");
map.put("sex", "nv");
map.put("age", "27");
map.put("phone", "15521331");
map.put("email", "812406fdf@qq.com");
map.put("idCard", "4305223243434332");
map.put("hobby", "跑步");
map.put("time", "2019年5月22日");
//源模板地址
String sourceFile = "C:\\Users\\Administrator\\Desktop\\工作笔记\\20210602\\还款记录Pdf\\还款记录模板.pdf";
//生成文件的目标地址
String targetFile = "C:\\Users\\Administrator\\Desktop\\工作笔记\\20210602\\还款记录Pdf\\test.pdf";
File templateFile = new File(sourceFile);
try {
/* 获取模板文件中的所有表单域
Set<String> templateFileFieldNames = PdfUtils.getTemplateFileFieldNames(sourceFile);
System.out.println(templateFileFieldNames);*/
PdfUtils.fillParam(map, FileUtils.readFileToByteArray(templateFile), targetFile);
} catch (IOException e) {
e.printStackTrace();
}
}
}
生成的文件