手机网站制作服务机构,做网站的一些费用,公司网站制作新手教程,海外购物appJava基于itextPDF实现pdf动态导出 1、制作PDF导出模板2 、集成itextpdf3 、编写实体4 、编写主要代码5、编写controller并测试补充#xff1a;踩坑记录 现在的业务越来越复杂了#xff0c;有些业务场景已经不能满足与EXCEL导出和WORD导出了#xff0c;例如准考证打印#x… Java基于itextPDF实现pdf动态导出 1、制作PDF导出模板2 、集成itextpdf3 、编写实体4 、编写主要代码5、编写controller并测试补充踩坑记录 现在的业务越来越复杂了有些业务场景已经不能满足与EXCEL导出和WORD导出了例如准考证打印电子证书等等这些都是动态数据导出的PDF。接下来我们就看一下怎么实现PDF的动态导出吧。
1、制作PDF导出模板
第一步我们需要制作一个PDF模板可以先使用WORD去制作制作完成以后再转为PDF。 当转为PDF以后我们就需要去给PDF设置表单域了表单域的名称和你要填充的数据名称需要一一对应。
这里推荐几个可以编辑表单域的软件Adobe Acrobat 、 万兴PDF、PDFill、Nitro 我这里懒省事用的万兴PDF免费版有水印具体哪个更好用一点请大家自行判断。
2 、集成itextpdf
接下来第二步则是在项目中集成itextpdf项目中使用的是SpringBoot 2.7 , 同时还集成了lombok.
dependencygroupIdcom.itextpdf/groupIdartifactIditextpdf/artifactIdversion5.5.13/version
/dependency3 、编写实体
编写导出PDF需要用到的实体这里注意实体中的属性名需要和表单域名一一对应。 同时为了方便测试在无参构造中初始化了一些默认数据。
package com.vinci.pdf.entity;import lombok.Data;/*** package: com.vinci.pdf.entity* className: Person* author: Vinci* description: 测试用实体* date: 2023/11/13 9:56*/
Data
public class Person {/*** description: 姓名**/private String name;/*** description: 国籍**/private String nationality;/*** description: 居住地**/private String address;/*** description: 民族**/private String nation;/*** description: 户籍地**/private String registeredResidence;/*** description: 身高 / 体重**/private String heightAndWeight;/*** description: 婚姻状况**/private String maritalStatus;/*** description: 年龄**/private Integer age;/*** description: 照片**/private String largeHeadPhoto;/*** description: 这里为了方便测试在无参构造直接初始化数据来模拟持久化数据。**/public Person() {this.name vinci;this.nationality 中国;this.address 江苏南京;this.nation 汉族;this.registeredResidence 河南漯河;this.heightAndWeight 178cm / 65Kg;this.maritalStatus 未婚;this.age 24;this.largeHeadPhoto Thread.currentThread().getContextClassLoader().getResource(static/header1.jpg).getFile();}}
4 、编写主要代码
在Service实现类中编写主要功能将数据填充到PDF中并实现导出。
package com.vinci.pdf.service.impl;import com.itextpdf.text.Document;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;
import com.vinci.pdf.entity.Person;
import com.vinci.pdf.service.api.PdfGenerateTestService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.Field;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Objects;/*** package: com.vinci.pdf.service.impl* className: PdfGenerateTestServiceImpl* author: Vinci* description: pdf生成测试接口实现* date: 2023/11/13 10:15*/
Service
public class PdfGenerateTestServiceImpl implements PdfGenerateTestService {/*** description: 日志服务**/private static final Logger log LoggerFactory.getLogger(PdfGenerateTestServiceImpl.class);/*** description: pdf生成* author: Vinci* date: 2023/11/13 10:25**/Overridepublic void pdfGenerate(HttpServletResponse response) throws UnsupportedEncodingException {// 模板地址URL resource Thread.currentThread().getContextClassLoader().getResource(templates/aipuu-y1mhx.pdf);if(resource null){throw new RuntimeException(没有找到模板);}String path resource.getPath();// PDF的文件名称 及响应头String fileName test.pdf;fileName URLEncoder.encode(fileName, UTF-8);response.setContentType(application/force-download);//如果想要下载文件的话这里的inline可以替换为 attachmentresponse.setHeader(Content-Disposition,fileName fileName);OutputStream ops null;ByteArrayOutputStream bos null;PdfStamper pdfStamper null;PdfReader pdfReader null;try {ops response.getOutputStream();pdfReader new PdfReader(path);bos new ByteArrayOutputStream();// 根据模板生成新的PDFpdfStamper new PdfStamper(pdfReader, bos);AcroFields form pdfStamper.getAcroFields();// 设置字体BaseFont font BaseFont.createFont(C:/WINDOWS/Fonts/SIMSUN.TTC,1,BaseFont.IDENTITY_H,BaseFont.EMBEDDED);form.addSubstitutionFont(font);// 获取数据(这里在无参构造中生成了一些数据实际开发中可用持久化数据来代替)Person person new Person();// 通过反射遍历来给PDF中的表单生成数据Field[] fields person.getClass().getDeclaredFields();for (Field field : fields) {field.setAccessible(true);String key field.getName();Object value field.get(person);if(!Objects.equals(key,largeHeadPhoto)){//处理文本数据form.setField(key, value.toString());}else{// 通过表单域名获取所在页和坐标左下角为起点int pageNo form.getFieldPositions(key).get(0).page;Rectangle signRect form.getFieldPositions(key).get(0).position;float x signRect.getLeft();float y signRect.getBottom();// 读图片Image image Image.getInstance(value.toString());// 获取操作的页面PdfContentByte under pdfStamper.getOverContent(pageNo);// 根据域的大小缩放图片image.scaleToFit(signRect.getWidth(), signRect.getHeight());// 添加图片image.setAbsolutePosition(x, y);under.addImage(image);}}// 设置PDF为只读pdfStamper.setFormFlattening(true);// 关闭资源pdfStamper.close();Document doc new Document();PdfCopy copy new PdfCopy(doc, ops);doc.open();PdfImportedPage importPage copy.getImportedPage(new PdfReader(bos.toByteArray()), 1);copy.addPage(importPage);doc.close();}catch (Exception e){log.error(发现异常,e);}finally {try {if (ops ! null) {ops.flush();ops.close();}if (pdfReader ! null) {pdfReader.close();}}catch (Exception e){log.error(发现异常,e);}}}}
5、编写controller并测试
编写Controller来方便我们通过浏览器的请求的方式去测试
package com.vinci.pdf.controller;import com.vinci.pdf.service.api.PdfGenerateTestService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;/*** package: com.vinci.pdf.controller* className: PdfGenerateTestController* author: Vinci* description:pdf生成测试controller* date: 2023/11/13 10:16*/
RestController
RequestMapping(/pdf)
public class PdfGenerateTestController {/*** description: 日志打印**/private static final Logger log LoggerFactory.getLogger(PdfGenerateTestController.class);/*** description: 业务接口**/Resourceprivate PdfGenerateTestService pdfGenerateTestService;/*** description: 测试pdf生成* author: Vinci* date: 2023/11/13 10:17**/GetMapping(value /generate)public void pdfGenerate(HttpServletResponse response){try{pdfGenerateTestService.pdfGenerate(response);}catch (Exception e){log.error(发现异常,e);}}
}
这里我们打开浏览器访问 http://localhost:8080/pdf/generate 发现PDF已经在下载了 下载成功后我们打开发现里面已经有数据了。
补充踩坑记录
使用万兴PDF编辑图片类型的表单域时一定要注意去掉背景色否则导出后你会看不到图片
本文代码下载地址https://gitee.com/vinci99/springboot-pdf-generate.git