Java代码生成PDF(包括文字单选复选等按钮)
1. 概述
1. 开源框架支持
- iText,生成PDF文档,还支持将XML、Html文件转化为PDF文件;
- Apache PDFBox,生成、合并PDF文档;
- docx4j,生成docx、pptx、xlsx文档,支持转换为PDF格式。
2.比较
- iText开源协议为AGPL,而其他两个框架协议均为Apache License v2.0。
- 使用PDFBox生成PDF就像画图似的,文字和图像根据页面坐标画上去的,需要根据字数手动换行。
- docx4j用来生成docx文档,提供了将WORD文档转换为PDF文档的功能,并不能直接生成PDF文档。
2. 第一种 itext生成pdf
1. 第一步 准备软件,编辑模版
微博关注vposy,这上面都是Adobe Acrobat 的软件破解版
打开软件,文件-》创建表单-》添加表单域
注意,表单中的表单域名字需要与传出一致
2. 第二步 导包
implementation 'com.itextpdf:itextpdf:5.5.13.3'
找不到可以去Maven仓库搜索 Maven仓库
3. 第三步 编写生成PDF工具类
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;
public class GeneratePDF {
/**
* @param fields
* @param data
* @throws IOException
* @throws DocumentException
*/
//单选、复选按钮除键值对外需要额外传true
private static void fillData(AcroFields fields, Map<String, String> data) throws IOException, DocumentException {
List<String> keys = new ArrayList<String>();
Map<String, AcroFields.Item> formFields = fields.getFields();
for (String key : data.keySet()) {
if (formFields.containsKey(key)) {
if (Objects.equals(key, "sfkygg") || Objects.equals(key, "sflhpm") || Objects.equals(key, "wscxz") || Objects.equals(key,"jmrsxz")){
String value = data.get(key);
fields.setField(key, value,true); // 为字段赋值,注意字段名称是区分大小写的
keys.add(key);
}else{
String value = data.get(key);
fields.setField(key, value); // 为字段赋值,注意字段名称是区分大小写的
keys.add(key);
}
}
}
for (String itemKey : formFields.keySet()) {
if (!keys.contains(itemKey)) {
fields.setField(itemKey, " ");
}
}
}
/**
* @param templatePdfPath 模板pdf路径
* @param generatePdfPath 生成pdf路径
* @param data 数据
*/
public static String generatePDF(String templatePdfPath, String generatePdfPath, Map<String, String> data) {
FileOutputStream fos = null;
ByteArrayOutputStream bos = null;
try {
PdfReader reader = new PdfReader(templatePdfPath);
bos = new ByteArrayOutputStream();
/* 将要生成的目标PDF文件名称 */
PdfStamper ps = new PdfStamper(reader, bos);
// BaseFont bf = BaseFont.createFont("/usr/share/fonts/zhFonts/SimSun.ttf",BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
BaseFont bf = BaseFont.createFont("/usr/share/fonts/SIMSUN.TTC,1",BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
// BaseFont bf = BaseFont.createFont("c://windows//fonts//simsun.ttc,1",BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
AcroFields s = ps.getAcroFields();
ArrayList<BaseFont> fontList = new ArrayList<BaseFont>();
fontList.add(bf);
/* 取出报表模板中的所有字段 */
AcroFields fields = ps.getAcroFields();
fields.setSubstitutionFonts(fontList);
fillData(fields, data);
/* 必须要调用这个,否则文档不会生成的 如果为false那么生成的PDF文件还能编辑,一定要设为true*/
ps.setFormFlattening(true);
ps.close();
fos = new FileOutputStream(generatePdfPath);
fos.write(bos.toByteArray());
fos.flush();
// generatePdfPath = "http://101.42.99.134:9001/pmxt/download/"+
generatePdfPath = generatePdfPath.replace("/usr/local/apps/pmxt-download","http://101.42.99.134:9001/pmxt/download");
return generatePdfPath;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
}
生成PDF传参参考手册:itext传参参考手册
4. 第四步 准备数据
domain实体类
点击查看代码
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.AcroFields;
import lombok.Data;
import org.springframework.data.annotation.Id;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
@Data
@TableName("busi_commission")
public class Commmission {
@TableId(type = IdType.AUTO)
private Integer id;
private String wthtbh;
@NotNull(message = "委托人不能为空")
@NotBlank(message = "委托人不能为空")
private String wtr;
private String wtdlr;
@NotNull(message = "拍卖人不能为空")
@NotBlank(message = "拍卖人不能为空")
private String pmr;
private String pmdlr;
@NotNull(message = "标的总名称不能为空")
@NotBlank(message = "标的总名称不能为空")
private String bdzmc;
@NotNull(message = "总保留价不能为空")
private BigDecimal zblj;
@NotNull(message = "总起拍价不能为空")
private BigDecimal zqpj;
// @NotNull(message = "总二次保留价不能为空")
private BigDecimal zecblj;
private float zjdbfb;
@NotNull(message = "拍卖方式不能为空")
@NotBlank(message = "拍卖方式不能为空")
private String pmfs;
private String wtpgr;
private String pgfycdr;
private String jdr;
private String jdfycdr;
@NotNull(message = "拍卖开始日期不能为空")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime pmksrq;
@NotNull(message = "拍卖地点不能为空")
@NotBlank(message = "拍卖地点不能为空")
private String pmdd;
@NotNull(message = "公告开始日期不能为空")
@JsonFormat(pattern = "yyyy-MM-dd")
private Date ggksrq;
@NotNull(message = "公告结束日期不能为空")
@JsonFormat(pattern = "yyyy-MM-dd")
private Date ggjsrq;
@NotNull(message = "是否可以公告不能为空")
private Boolean sfkygg;
private BigDecimal bzj;
private float bzjzbljbfb;
// @NotNull(message = "最低竞买人数不能为空")
private Integer zdjmrs;
@NotNull(message = "是否同意联合拍卖不能为空")
private Boolean sflhpm;
@NotNull(message = "交付人不能为空")
@NotBlank(message = "交付人不能为空")
private String jfr;
@NotNull(message = "交付截止日期不能为空")
@JsonFormat(pattern = "yyyy-MM-dd")
private Date jfjzrq;
@NotNull(message = "交付地点不能为空")
@NotBlank(message = "交付地点不能为空")
private String jfdd;
@NotNull(message = "交付方式不能为空")
@NotBlank(message = "交付方式不能为空")
private String jffs;
@NotNull(message = "保管费用承担人不能为空")
@NotBlank(message = "保管费用承担人不能为空")
private String bgfcdr;
@NotNull(message = "价款支付方式不能为空")
@NotBlank(message = "价款支付方式不能为空")
private String jkzffs;
@NotNull(message = "价款支付期限不能为空")
@NotBlank(message = "价款支付期限不能为空")
private String jkzfqx;
@NotNull(message = "拍卖撤除原因不能为空")
@NotBlank(message = "拍卖撤除原因不能为空")
private String pmccyy;
@NotNull(message = "标的未售出选择不能为空")
@NotBlank(message = "标的未售出选择不能为空")
private String wscxz;
private Integer xdlhts;
private String wlhclfs;
// @NotNull(message = "保密约定不能为空")
// @NotBlank(message = "保密内容不能为空")
private String bmnr;
private Integer wyj;
private float wyjzbljbfb;
@NotNull(message = "违约责任不能为空")
@NotBlank(message = "违约责任不能为空")
private String wyzr;
@NotNull(message = "争议解决选择不能为空")
@NotBlank(message = "争议解决选择不能为空")
private String zyjjxz;
@NotNull(message = "仲裁委员会名称不能为空")
@NotBlank(message = "仲裁委员会名称不能为空")
private String zcwyhmc;
@NotNull(message = "人民法院名称不能为空")
@NotBlank(message = "人民法院名称不能为空")
private String rmfymc;
private String ydy;
private String yde;
private String yds;
@NotNull(message = "合同开始日期不能为空")
@JsonFormat(pattern = "yyyy-MM-dd")
private Date htksrq;
@NotNull(message = "合同结束日期不能为空")
@JsonFormat(pattern = "yyyy-MM-dd")
private Date htjsrq;
private String wtrqz;
private String wtrkhh;
private String wtrzh;
private String wtrdh;
@JsonFormat(pattern = "yyyy-MM-dd")
private Date wtrqzrq;
private String pmrkhh;
private String pmrzh;
private String pmrdh;
@JsonFormat(pattern = "yyyy-MM-dd")
private Date pmrqzrq;
private String pmdw;
private BigDecimal pmje;
private String remark;
private String ggmtmc;
private float yjzcjjbfb;
@NotNull(message = "合理费用包括不能为空")
@NotBlank(message = "合理费用包括不能为空")
private String hlfybk;
@NotNull(message = "合理费用金额不能为空")
private BigDecimal hlfyje;
@NotNull(message = "合理费限制天数不能为空")
private Integer hlfxzts;
@NotNull(message = "委托合同名称不能为空")
private String wthtmc;
@TableLogic
private Boolean deleteflag;
private Boolean jmrsxz;
private String pmrqz;
private Integer qyid;
public Map<String,String> toMap() throws DocumentException, IOException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Map<String,String> map = new HashMap<>();
map.put("wthtbh",wthtbh);
map.put("wtr",wtr);
map.put("wtdlr",wtdlr);
map.put("pmr",pmr);
map.put("pmdlr",pmdlr);
map.put("bdzmc",bdzmc);
if(zblj == null){
map.put("zblj", "");
}else {
map.put("zblj", String.valueOf(zblj));
}
if(zqpj == null){
map.put("zqpj", "");
}else {
map.put("zqpj", String.valueOf(zqpj));
}
if(zecblj == null){
map.put("zecblj", "");
}else {
map.put("zecblj", String.valueOf(zecblj));
}
if(zjdbfb == 0.0){
map.put("zjdbfb", "");
}else {
map.put("zjdbfb", String.valueOf(zjdbfb));
}
map.put("pmfs",pmfs);
map.put("wtpgr",wtpgr);
map.put("pgfycdr",pgfycdr);
map.put("jdr",jdr);
map.put("jdfycdr",jdfycdr);
if(pmksrq == null){
map.put("year1","");
map.put("month1","");
map.put("day1","");
map.put("time","");
}else {
String [] date = String.valueOf(pmksrq).split("T");
String [] date1 = String.valueOf(date[0]).split("-");
map.put("year1",date1[0]);
map.put("month1",date1[1]);
map.put("day1",date1[2]);
map.put("time",date[1]);
}
map.put("pmdd",pmdd);
if(ggksrq == null){
map.put("year2", "");
map.put("month2", "");
map.put("day2", "");
}else {
String [] date2 = sdf.format(ggksrq).split("-");
map.put("year2", date2[0]);
map.put("month2", date2[1]);
map.put("day2", date2[2]);
}
if(ggjsrq == null){
map.put("year3", "");
map.put("month3", "");
map.put("day3", "");
}else {
String [] date3 = sdf.format(ggjsrq).split("-");
map.put("year3", date3[0]);
map.put("month3", date3[1]);
map.put("day3", date3[2]);
}
map.put("sfkygg", String.valueOf(sfkygg));
if(bzj == null){
map.put("bzj", "");
}else {
map.put("bzj", String.valueOf(bzj));
}
if(bzjzbljbfb == 0.0){
map.put("bzjzbljbfb", "");
}else {
map.put("bzjzbljbfb", String.valueOf(bzjzbljbfb));
}
if(zdjmrs == null){
map.put("zdjmrs", "");
}else {
map.put("zdjmrs", String.valueOf(zdjmrs));
}
map.put("sflhpm", String.valueOf(sflhpm));
map.put("jfr",jfr);
if(jfjzrq == null){
map.put("year4", "");
map.put("month4", "");
map.put("day4", "");
}else {
String [] date4 = sdf.format(jfjzrq).split("-");
map.put("year4", date4[0]);
map.put("month4", date4[1]);
map.put("day4", date4[2]);
}
map.put("jfdd",jfdd);
map.put("jffs",jffs);
map.put("bgfcdr",bgfcdr);
map.put("jkzffs",jkzffs);
map.put("jkzfqx",jkzfqx);
map.put("pmccyy",pmccyy);
map.put("wscxz",wscxz);
if(xdlhts == null){
map.put("xdlhts", "");
}else {
map.put("xdlhts", String.valueOf(xdlhts));
}
map.put("wlhclfs",wlhclfs);
map.put("bmnr",bmnr);
if(wyj == null){
map.put("wyj", "");
}else {
map.put("wyj", String.valueOf(wyj));
}
if(wyjzbljbfb == 0.0){
map.put("wyjzbljbfb", "");
}else {
map.put("wyjzbljbfb", String.valueOf(wyjzbljbfb));
}
map.put("wyzr",wyzr);
map.put("zyjjxz",zyjjxz);
map.put("zcwyhmc",zcwyhmc);
map.put("rmfymc",rmfymc);
map.put("ydy",ydy);
map.put("yde",yde);
map.put("yds",yds);
if(htksrq == null){
map.put("year5", "");
map.put("month5", "");
map.put("day5", "");
}else {
String [] date5 = sdf.format(htksrq).split("-");
map.put("year5", date5[0]);
map.put("month5", date5[1]);
map.put("day5", date5[2]);
}
if(htjsrq == null){
map.put("year6", "");
map.put("month6", "");
map.put("day6", "");
}else {
String [] date6 = sdf.format(htjsrq).split("-");
map.put("year6", date6[0]);
map.put("month6", date6[1]);
map.put("day6", date6[2]);
}
map.put("wtrqz",wtrqz);
map.put("wtrkhh",wtrkhh);
map.put("wtrzh",wtrzh);
map.put("wtrdh",wtrdh);
if(wtrqzrq == null){
map.put("year7", "");
map.put("month7", "");
map.put("day7", "");
}else {
String [] date7 = sdf.format(wtrqzrq).split("-");
map.put("year7", date7[0]);
map.put("month7", date7[1]);
map.put("day7", date7[2]);
}
map.put("pmrkhh",pmrkhh);
map.put("pmrzh",pmrzh);
map.put("pmrdh",pmrdh);
if(pmrqzrq == null){
map.put("year8", "");
map.put("month8", "");
map.put("day8", "");
}else {
String [] date8 = sdf.format(pmrqzrq).split("-");
map.put("year8", date8[0]);
map.put("month8", date8[1]);
map.put("day8", date8[2]);
}
map.put("pmdw",pmdw);
if(pmje == null){
map.put("pmje", "");
}else {
map.put("pmje", String.valueOf(pmje));
}
map.put("remark",remark);
map.put("ggmtmc",ggmtmc);
if(yjzcjjbfb == 0.0){
map.put("yjzcjjbfb", "");
}else {
map.put("yjzcjjbfb", String.valueOf(yjzcjjbfb));
}
map.put("hlfybk",hlfybk);
if(hlfyje == null){
map.put("hlfyje", "");
}else {
map.put("hlfyje", String.valueOf(hlfyje));
}
if(hlfxzts == 0.0){
map.put("hlfxzts", "");
}else {
map.put("hlfxzts", String.valueOf(hlfxzts));
}
map.put("jmrsxz",String.valueOf(jmrsxz));
map.put("pmrqz",String.valueOf(pmrqz));
return map;
}
}
Mapper
点击查看代码
@Select("select * from busi_commission where wthtbh = #{wthtbh}")
Commmission getbywthtbh(String wthtbh);
Service
点击查看代码
public String gethtbh(){
return commissionMapper.gethtbh();
}
// 用于返回生成PDF所需标的清单信息
public Map<String,String> getlot(String wthtbh){
List<Map<String,Object>> maps= commissionMapper.getlot(wthtbh);
Map<String,String> map = new HashMap<>();
for (int i = 0; i < maps.size(); i++) {
int a = i+1;
map.put("bdlx"+ a, String.valueOf(maps.get(i).get("bdlx")));
map.put("number"+a, String.valueOf( maps.get(i).get("number")));
map.put("blj"+a, String.valueOf(maps.get(i).get("blj")));
map.put("other"+a, String.valueOf(maps.get(i).get("other")));
}
System.out.println(map);
return map;
}
Controller
点击查看代码
@PostMapping("/createPdf")
public ReturnResult createPdf(@NotNull(message = "合同编号不能为空") String wthtbh) throws DocumentException, IOException {
String newPDFPath1 = "";
newPDFPath1 = newPDFPath + wthtbh + ".pdf";
Map<String,String> datemap = commissionService.getbywthtbh(wthtbh).toMap();
datemap.putAll(commissionService.getlot(wthtbh));
System.out.println(commissionService.getbywthtbh(wthtbh).toMap());
// pdfout(templatePath,newPDFPath,datemap,10);
return ReturnResult.buildSuccessResult(generatePDF(templatePath,newPDFPath1,datemap));
}
2. 第二种pdfbox
3. 第三种docx4j+freemarker
docx4j+freemarker
过程:doc保存为xml格式,改后缀名为ftl,放入resouce里面,格式化一下
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?