依赖
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13</version>
</dependency>
<!--字体-->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
工具类
package com.yunfang.fdcjj.common;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import com.yunfang.common.utils.StringUtils;
import org.springframework.core.io.ClassPathResource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class PDFUtil {
private static BaseFont baseFont_simfang;
private static BaseFont baseFont_simsong;
private static BaseFont baseFont;
static{
try {
//使用自定义字体,生成文件会过大
baseFont_simfang=BaseFont.createFont("/static/font/simfang.ttf",BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);
baseFont_simsong=BaseFont.createFont("/static/font/simsong.ttf",BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);
//使用 itext 内字体
baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
} catch (Exception e) {
e.printStackTrace();
}
}
public static class PDFParam{
Map<String, Object> datas;
Map<String, Object> imgDatas;
Map<String,byte[]> qrDatas;
public Map<String, Object> getDatas() {
return datas;
}
public void setDatas(Map<String, Object> datas) {
this.datas = datas;
}
public Map<String, Object> getImgDatas() {
return imgDatas;
}
public void setImgDatas(Map<String, Object> imgDatas) {
this.imgDatas = imgDatas;
}
public Map<String, byte[]> getQrDatas() {
return qrDatas;
}
public void setQrDatas(Map<String, byte[]> qrDatas) {
this.qrDatas = qrDatas;
}
}
public static void pdfExport(HttpServletResponse response, String templatePath, Map<String, Object> datas) throws IOException {
pdfExport(response,templatePath,datas,null);
}
public static void pdfExport(HttpServletResponse response, String templatePath, Map<String, Object> datas, Map<String, Object> imgDatas) throws IOException {
ClassPathResource cpr = new ClassPathResource(templatePath);
pdfExport(response.getOutputStream(),cpr.getInputStream(),datas,imgDatas,null);
}
public static void pdfExport(HttpServletResponse response, String templatePath, Map<String, Object> datas, Map<String, Object> imgDatas,Map<String,byte[]> qrcodes) throws IOException {
ClassPathResource cpr = new ClassPathResource(templatePath);
pdfExport(response.getOutputStream(),cpr.getInputStream(),datas,imgDatas,qrcodes);
}
public static void pdfExport(OutputStream out, InputStream templateIn, Map<String, Object> datas){
pdfExport(out,templateIn,datas,null,null);
}
public static void pdfExport(OutputStream out, InputStream templateIn, Map<String, Object> datas, Map<String, Object> imgDatas,Map<String,byte[]> qrcodes){
ByteArrayOutputStream bos = null;
PdfStamper stamper = null;
PdfReader template = null;
try {
// 读取PDF模板表单
template = new PdfReader(templateIn);
// 字节数组流,用来缓存文件流
bos = new ByteArrayOutputStream();
// 根据模板表单生成一个新的PDF
stamper = new PdfStamper(template, bos);
// 获取新生成的PDF表单
AcroFields form = stamper.getAcroFields();
// 给表单生成中文字体,这里采用系统字体,不设置的话,中文显示会有问题
//BaseFont simsun_font = BaseFont.createFont("/static/font/simsong.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
//BaseFont simsun_font = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false);
//form.addSubstitutionFont(simsun_font);
// 遍历data,给pdf表单赋值
if(datas != null){
for(String key : datas.keySet()){
int type = form.getFieldType(key);
switch (type){
case 2:
//form.setFieldProperty(key, "setfflags", 1, (int[])null);
form.setField(key, StringUtils.isNull(datas.get(key))?"":datas.get(key).toString(), true);
break;
default:
form.setFieldProperty(key, "textfont", baseFont_simsong, (int[])null);
//form.setFieldProperty(key, "textsize", 11f, (int[])null);
form.setField(key, StringUtils.isNull(datas.get(key))?"":datas.get(key).toString());
break;
}
}
}
if(imgDatas != null){
for(String key : imgDatas.keySet()){
int pageNo = form.getFieldPositions(key).get(0).page;
Rectangle signRect = form.getFieldPositions(key).get(0).position;
float x = signRect.getLeft();
float y = signRect.getBottom();
//根据路径或Url读取图片
Image image;
try {
image = Image.getInstance(imgDatas.get(key).toString());
}catch (FileNotFoundException e){
continue;
}
//获取图片页面
PdfContentByte under = stamper.getOverContent(pageNo);
//图片大小自适应
image.scaleToFit(signRect.getWidth(), signRect.getHeight());
//添加图片
image.setAbsolutePosition(x, y);
under.addImage(image);
}
}
if(qrcodes != null){
for(String key : qrcodes.keySet()){
int pageNo = form.getFieldPositions(key).get(0).page;
Rectangle signRect = form.getFieldPositions(key).get(0).position;
float x = signRect.getLeft();
float y = signRect.getBottom();
//根据路径或Url读取图片
Image image = Image.getInstance(qrcodes.get(key));
//获取图片页面
PdfContentByte under = stamper.getOverContent(pageNo);
//图片大小自适应
image.scaleToFit(signRect.getWidth(), signRect.getHeight());
//添加图片
image.setAbsolutePosition(x, y);
under.addImage(image);
}
}
// 表明该PDF不可修改
stamper.setFormFlattening(true);
// 关闭资源
stamper.close();
// 将ByteArray字节数组中的流输出到out中(即输出到浏览器)
Document doc = new Document();
PdfReader reader = new PdfReader(bos.toByteArray());
PdfCopy copy = new PdfCopy(doc, out);
doc.open();
int page = reader.getNumberOfPages();
for(int j = 1; j <= page; ++j) {
doc.newPage();
PdfImportedPage copypage = copy.getImportedPage(reader, j);
copy.addPage(copypage);
}
doc.close();
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if (out != null) {
out.flush();
out.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
public static void pdfExportBatch(OutputStream out, String templatePath, List<PDFParam> pdfParamList){
ByteArrayOutputStream bos = null;
PdfStamper stamper = null;
PdfReader template = null;
try {
List<PdfReader> list = new ArrayList<>();
// 给表单生成中文字体,这里采用系统字体,不设置的话,中文显示会有问题
//BaseFont simsun_font = BaseFont.createFont("/static/font/simsong.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
for (PDFParam pdfParam:pdfParamList) {
Map<String, Object> datas = pdfParam.getDatas();
Map<String, Object> imgDatas = pdfParam.getImgDatas();
Map<String,byte[]> qrcodes = pdfParam.getQrDatas();
// 读取PDF模板表单
ClassPathResource cpr = new ClassPathResource(templatePath);
template = new PdfReader(cpr.getInputStream());
// 字节数组流,用来缓存文件流
bos = new ByteArrayOutputStream();
// 根据模板表单生成一个新的PDF
stamper = new PdfStamper(template, bos);
// 获取新生成的PDF表单
AcroFields form = stamper.getAcroFields();
//BaseFont simsun_font = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false);
//form.addSubstitutionFont(simsun_font);
// 遍历data,给pdf表单赋值
if(datas != null){
for(String key : datas.keySet()){
int type = form.getFieldType(key);
switch (type){
case 2:
//form.setFieldProperty(key, "setfflags", 1, (int[])null);
form.setField(key, StringUtils.isNull(datas.get(key))?"":datas.get(key).toString(), true);
break;
default:
form.setFieldProperty(key, "textfont", baseFont_simsong, (int[])null);
//form.setFieldProperty(key, "textsize", 11f, (int[])null);
form.setField(key,StringUtils.isNull(datas.get(key))?"": datas.get(key).toString());
break;
}
}
}
if(imgDatas != null){
for(String key : imgDatas.keySet()){
int pageNo = form.getFieldPositions(key).get(0).page;
Rectangle signRect = form.getFieldPositions(key).get(0).position;
float x = signRect.getLeft();
float y = signRect.getBottom();
//根据路径或Url读取图片
Image image;
try {
image = Image.getInstance(imgDatas.get(key).toString());
}catch (FileNotFoundException e){
continue;
}
//获取图片页面
PdfContentByte under = stamper.getOverContent(pageNo);
//图片大小自适应
image.scaleToFit(signRect.getWidth(), signRect.getHeight());
//添加图片
image.setAbsolutePosition(x, y);
under.addImage(image);
}
}
if(qrcodes != null){
for(String key : qrcodes.keySet()){
int pageNo = form.getFieldPositions(key).get(0).page;
Rectangle signRect = form.getFieldPositions(key).get(0).position;
float x = signRect.getLeft();
float y = signRect.getBottom();
//根据路径或Url读取图片
Image image = Image.getInstance(qrcodes.get(key));
//获取图片页面
PdfContentByte under = stamper.getOverContent(pageNo);
//图片大小自适应
image.scaleToFit(signRect.getWidth(), signRect.getHeight());
//添加图片
image.setAbsolutePosition(x, y);
under.addImage(image);
}
}
// 表明该PDF不可修改
stamper.setFormFlattening(true);
// 关闭资源
stamper.close();
list.add(new PdfReader(bos.toByteArray()));
}
// 将ByteArray字节数组中的流输出到out中(即输出到浏览器)
Document doc = new Document();
PdfCopy copy = new PdfCopy(doc, out);
doc.open();
for (PdfReader reader:list) {
int page = reader.getNumberOfPages();
for(int j = 1; j <= page; ++j) {
doc.newPage();
PdfImportedPage copypage = copy.getImportedPage(reader, j);
copy.addPage(copypage);
}
}
doc.close();
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if (out != null) {
out.flush();
out.close();
}
if (stamper != null) {
stamper.close();
}
if (template != null) {
template.close();
}
if (bos != null) {
bos.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
public static PdfPCell createCell(String value, Font font, int align){
PdfPCell cell = new PdfPCell();
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setHorizontalAlignment(align);
cell.setPhrase(new Phrase());
return cell;
}
public static PdfPCell createCell(String value, Font font){
PdfPCell cell = new PdfPCell();
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
cell.setPhrase(new Phrase(value,font));
return cell;
}
public static PdfPCell createCell(String value, Font font, int align, int colspan){
PdfPCell cell = new PdfPCell();
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setHorizontalAlignment(align);
cell.setColspan(colspan);
cell.setPhrase(new Phrase(value,font));
return cell;
}
public static PdfPCell createCell(String value, Font font, int align, int colspan, boolean boderFlag){
PdfPCell cell = new PdfPCell();
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setHorizontalAlignment(align);
cell.setColspan(colspan);
cell.setPhrase(new Phrase(value,font));
cell.setPadding(.0f);
if(!boderFlag){
cell.setBorder(0);
cell.setPaddingTop(15.0f);
cell.setPaddingBottom(8.0f);
}
return cell;
}
public static PdfPCell createCell(String value, Font font, int align, boolean boderFlag){
PdfPCell cell = new PdfPCell();
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setHorizontalAlignment(align);
cell.setPhrase(new Phrase(value,font));
cell.setPadding(4.0f);
cell.setMinimumHeight(40);
if(!boderFlag){
cell.setBorder(0);
cell.setPaddingTop(15.0f);
cell.setPaddingBottom(8.0f);
}
return cell;
}
public static PdfPTable createTable(float width){
PdfPTable table = new PdfPTable(1);
try{
table.setTotalWidth(width);
table.setLockedWidth(true);
table.setHorizontalAlignment(Element.ALIGN_CENTER);
table.setWidthPercentage(100);//设置表格宽度为100%
}catch(Exception e){
e.printStackTrace();
}
return table;
}
private static PdfPTable createTable(int colNum, float[] columnWidths) {
PdfPTable table = new PdfPTable(colNum);
try {
table.setWidths(columnWidths);
} catch (DocumentException e) {
e.printStackTrace();
}
table.setSpacingBefore(20f);//设置页边距
table.setWidthPercentage(95);//设置表格宽度为100%
return table;
}
public static void generateSimpleTablePDF(String title, Map<String,String> datas, OutputStream out) throws Exception{
Document document = new Document();
PdfWriter writer=null;
document.setPageSize(PageSize.A4);// 设置页面大小
document.setMargins(0,0,10,5);//左右上下
try {
writer=PdfWriter.getInstance(document,out);
document.open();
} catch (Exception e) {
e.printStackTrace();
}
PdfPTable title_table = createTable(600);
title_table.addCell(createCell(title, new Font(baseFont_simsong, 25),Element.ALIGN_CENTER,false));
document.add(title_table);
float[] columnWidths = {10, 20};//表格每一列的宽度
PdfPTable table = createTable(2,columnWidths);
if(datas!=null){
for (Map.Entry entry:datas.entrySet()) {
table.addCell(createCell(entry.getKey().toString(), new Font(baseFont_simfang, 17),Element.ALIGN_LEFT,true));
table.addCell(createCell(entry.getValue().toString(), new Font(baseFont_simfang, 17), Element.ALIGN_LEFT,true));
}
}
document.add(table);
PdfPTable title_table1 = createTable(600);
title_table1.addCell(createCell("郑重申明:谨此保证,本表所填报内容及所附证明材料真实、完整 ", new Font(baseFont_simfang, 15),Element.ALIGN_RIGHT,false));
document.add(title_table1);
document.close();
writer.close();
}
}
测试
public void pdfExport(HttpServletResponse response){
String templatePath = "/pdf-templates/test.pdf";
Map<String,Object> map = new HashMap<>();
Map<String,Object> imgmap = new HashMap<>();
map.put("no","20220617001");
map.put("name","sajfl");
map.put("xb","m");
map.put("hm","18313006955");
map.put("dw","云南省昆明市五华区");
map.put("check_1","是");
map.put("check_2","是");
map.put("bz","备注");
imgmap.put("tp","https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fss2.meipian.me%2Fusers%2F107777579%2F36e69800cb1865176d8926b1fea9e671.jpg%3Fmeipian-raw%2Fbucket%2Fivwen%2Fkey%2FdXNlcnMvMTA3Nzc3NTc5LzM2ZTY5ODAwY2IxODY1MTc2ZDg5MjZiMWZlYTllNjcxLmpwZw%3D%3D%2Fsign%2F606cf16a09f60794f5c0f241a44854d9.jpg&refer=http%3A%2F%2Fss2.meipian.me&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1658044011&t=6583ae19c436a5fe444c69bb679bbb0e");
try {
String fileName = URLEncoder.encode("个人信息.pdf", "UTF-8");
// 设置响应头
response.setContentType("application/force-download");
response.setHeader("Content-Disposition",
"attachment;fileName=" + fileName);
PDFUtil.pdfExport(response.getOutputStream(),templatePath,map,imgmap);
} catch (Exception e) {
e.printStackTrace();
}
}