前言
前一阵子接到需求,需要把数据填充到pdf的表单中,生成pdf文件并发起CA签章。今天有空(划水)记录下生产模板文件过程。
注意:生成pdf表单文件需要Adobe Acrobat X Pro 软件
一、设计PDF模板
1、先在word中设计一个表格:
2、使用Acrobat软件大家刚才设计的表单word
3、编辑表单域
4、 修改表单域的属性
文本框
选择框
注意这边导出值为ON,且复选框默认为已选中(项目中所用依赖版本比较低,生产的pdf会出现√显示为×的情况所以逆向思维改为选择否的情况)
至此模板文件就准备好了。
二、后端代码
1、pom依赖
注意itext-asian依赖是为了解决生产pdf字体问题, hutool是为了file转换字节数组
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.4.3</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.3.3</version>
</dependency>
2、详细代码
选择框 表单域选择时默认为选择状态 如果为on则是对钩 所以只需把不需要的表单字段设置为不为on的值即可
package com.hua.utils;
import cn.hutool.core.io.FileUtil;
import com.itextpdf.text.Document;
import com.itextpdf.text.pdf.*;
import org.apache.commons.lang3.StringUtils;
import sun.misc.BASE64Decoder;
import java.io.*;
import java.util.*;
/**
* @Author 云梦轻掩楼
* @Date 2024-05-10 08:39
* @Description
**/
public class PDFUtil {
public static Boolean base64StringToPdf(String base64Content, String filePath) throws IOException {
BASE64Decoder decoder = new BASE64Decoder();
BufferedInputStream bis = null;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
try {
byte[] bytes = decoder.decodeBuffer(base64Content);//base64编码内容转换为字节数组
ByteArrayInputStream byteInputStream = new ByteArrayInputStream(bytes);
bis = new BufferedInputStream(byteInputStream);
File file = new File(filePath);
File path = file.getParentFile();
if (!path.exists()) {
path.mkdirs();
}
fos = new FileOutputStream(file);
bos = new BufferedOutputStream(fos);
byte[] buffer = new byte[1024];
int length = bis.read(buffer);
while (length != -1) {
bos.write(buffer, 0, length);
length = bis.read(buffer);
}
bos.flush();
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
bis.close();
fos.close();
bos.close();
}
return true;
}
public static byte[] getLocalFileById(String path) throws IOException {
byte[] f = null;
java.io.File file = new java.io.File(path);
if (file.exists()) {
f = FileUtil.readBytes(file);
}else{
}
return f;
}
public static void main(String[] args) throws Exception {
//模板文件路径
String resourcePath = "template/testTemplate.pdf";
String TemplatePDF = PDFUtil.class.getClassLoader().getResource(resourcePath).getPath();
//生成文件地址
String url = "D:/online/test.pdf";
FileOutputStream outstream = new FileOutputStream(url);
ArrayList<ByteArrayOutputStream> baos = new ArrayList<ByteArrayOutputStream>();
Map<String, String> sqbdata = new HashMap<String, String>();
//组装数据
sqbdata.put("name", "云梦轻掩楼");
sqbdata.put("address", "河北省sass");
sqbdata.put("phone", "11111");
sqbdata.put("identity", "A");
String yh = "1";
//选择框 表单域选择时默认为选择状态 如果为on则是对钩 所以只需把不需要的表单字段设置为不为on的值即可
if (org.apache.commons.lang3.StringUtils.isNotBlank(yh)){
switch (yh){
case "1":
sqbdata.put("yh_2", "no");
sqbdata.put("yh_4", "no");
break;
case "2":
sqbdata.put("yh_1", "no");
sqbdata.put("yh_3", "no");
break;
}
}
ByteArrayOutputStream fos = CreatePdfStream(TemplatePDF, sqbdata);
baos.add(fos);
if (baos.size() > 0) {
Document doc = new Document();
PdfCopy pdfCopy = new PdfCopy(doc, outstream);
doc.open();
PdfImportedPage impPage = null;
PdfReader reader = null;
for (ByteArrayOutputStream bao : baos) {
reader = new PdfReader(bao.toByteArray());
int page = reader.getNumberOfPages();
for (int p = 1; p <= page; p++) {
impPage = pdfCopy.getImportedPage(reader, p);
pdfCopy.addPage(impPage);
}
}
doc.close();
}
}
private static ByteArrayOutputStream CreatePdfStream(String tplName, Map<String, String> data) throws Exception {
ByteArrayOutputStream bao = new ByteArrayOutputStream();
PdfReader reader = new PdfReader(tplName);
PdfStamper stamp = new PdfStamper(reader, bao);
AcroFields form = stamp.getAcroFields();
//设置字体
BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
ArrayList<BaseFont> fontList = new ArrayList<BaseFont>(1);
fontList.add(bf);
form.setSubstitutionFonts(fontList);
stamp.setFormFlattening(false);
Set<String> fields = form.getFields().keySet();
for (String _key : fields) {
if (data.containsKey(_key)) {
if (StringUtils.isNotBlank(data.get(_key))) {
String _value = String.valueOf(data.get(_key));
form.setField(_key, _value);
}
}
}
stamp.setFormFlattening(true);
stamp.close();
reader.close();
return bao;
}
}