Java-实现PDF合同模板填写内容并导出PDF文件

news/2025/3/5 8:47:18/

可用于公司用户合同导出pdf文件

效果图

一、导入所需要jar包

        <!--生成PDF--><dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.11</version></dependency><dependency><groupId>com.itextpdf</groupId><artifactId>itext-asian</artifactId><version>5.2.0</version></dependency><dependency><groupId>org.icepdf.os</groupId><artifactId>icepdf-core</artifactId><version>6.1.2</version></dependency><dependency><groupId>org.apache.pdfbox</groupId><artifactId>fontbox</artifactId><version>2.0.12</version></dependency><dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>2.0.12</version></dependency>

二、工具类代码实现

java">package com.example.excel.pdf;import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.itextpdf.text.Document;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfCopy;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import lombok.extern.slf4j.Slf4j;import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;/*** @author: reshui* description:* DateTime:2025/2/25-17:40*/
@Slf4j
public class PdfTemplateFillUtil {/*** 文件暂存地址*/public static final String TEMP_FILE_PATH = System.getProperty("java.io.tmpdir");/*** pdf文件暂存地址*/private static final String FILE_PATH = TEMP_FILE_PATH + File.separator + "generate_pdf";/*** 时间格式*/public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";public static void main(String[] args) {Map<String, Object> paramsMap = new HashMap<String, Object>();Map<String, Object> textAreaMap = new HashMap<String, Object>();Map<String, Object> imageAreaMap = new HashMap<String, Object>();textAreaMap.put("partyAName", "胡图图");textAreaMap.put("partyBName", "胡英俊");textAreaMap.put("address", "翻斗大街翻斗花园二号楼1001室");textAreaMap.put("systemOrderNumber", "Vx2024121315555020011");textAreaMap.put("idCard", "44xxxxxxxxxxx132123");textAreaMap.put("mobile", "185700xxxxxx");textAreaMap.put("remark", "     * BaseFont.NOT_EMBEDDED该参数指定是否将字体嵌入到生成的 PDF 文件中。BaseFont.NOT_EMBEDDED 表示不嵌入字体,即生成的 PDF 文件不会包含字体文件本身,而是依赖于查看 PDF 的设备上是否安装了相应的字体。如果设置为 BaseFont.EMBEDDED,则会将字体文件嵌入到 PDF 中,确保在任何设备上都能正确显示字体,但会增加 PDF 文件的大小。\n");String formatDateTime = DateUtil.formatDateTime(new Date());textAreaMap.put("now", formatDateTime);textAreaMap.put("haha", "你好呀,我是胡图图");textAreaMap.put("checkNow", "yes");textAreaMap.put("check2", "yes");paramsMap.put("textAreaMap", textAreaMap);imageAreaMap.put("companySign", "https://profile-avatar.csdnimg.cn/128f2647a3ac408eafb94c7a6706689b_weixin_42477252.jpg!1");imageAreaMap.put("signatureImg", "https://profile-avatar.csdnimg.cn/128f2647a3ac408eafb94c7a6706689b_weixin_42477252.jpg!1");paramsMap.put("imageAreaMap", imageAreaMap);easyGeneratePdf(paramsMap, "C:\\Users\\86138\\Desktop\\xxx\\123.pdf");}public static void easyGeneratePdf(Map<String, Object> areaMap, String fileName, String readPdfTemplateUrl) {String formatDateTimeStamp = DateUtil.format(new Date(), YYYYMMDDHHMMSS);String pdfFilePath = FILE_PATH + File.separator + formatDateTimeStamp + StrUtil.UNDERLINE + fileName + ".pdf";FileUtil.touch(pdfFilePath);generatePdf(areaMap, pdfFilePath, readPdfTemplateUrl);}public static void easyGeneratePdf(Map<String, Object> areaMap, String readPdfTemplateUrl) {String formatDateTimeStamp = DateUtil.format(new Date(), YYYYMMDDHHMMSS);String pdfFilePath = FILE_PATH + File.separator + formatDateTimeStamp + ".pdf";FileUtil.touch(pdfFilePath);generatePdf(areaMap, pdfFilePath, readPdfTemplateUrl);}/*** 模板填充生成PDF** @param areaMap                  域集合* @param outPutPdfFilePath        输出文件路径* @param readPdfTemplateUrlOrPath 读取pdf模板路径*                                 Linix 字体*                                 BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);*                                 Windows 字体*                                 BaseFont bf = BaseFont.createFont("c://windows//fonts//simsunb.ttf" , BaseFont.IDENTITY_H, BaseFont.EMBEDDED);*                                 <p>*                                 BaseFont.IDENTITY_H这个参数指定了字符编码。BaseFont.IDENTITY_H 表示使用 Unicode 水平书写方向的编码,这对于支持中文等多语言字符非常重要。如果不使用合适的编码,可能会导致字符显示乱码。*                                 BaseFont.NOT_EMBEDDED该参数指定是否将字体嵌入到生成的 PDF 文件中。BaseFont.NOT_EMBEDDED 表示不嵌入字体,即生成的 PDF 文件不会包含字体文件本身,而是依赖于查看 PDF 的设备上是否安装了相应的字体。如果设置为 BaseFont.EMBEDDED,则会将字体文件嵌入到 PDF 中,确保在任何设备上都能正确显示字体,但会增加 PDF 文件的大小。*/protected static synchronized File generatePdf(Map<String, Object> areaMap, String outPutPdfFilePath, String readPdfTemplateUrlOrPath) {PdfReader reader;FileOutputStream out;ByteArrayOutputStream bos;PdfStamper stamper;PdfTemplateFillConfig config = getSystemType();try {Document doc = new Document();BaseFont bf = BaseFont.createFont(config.getFontName(), config.getEncoding(), config.getEmbedded());out = new FileOutputStream(outPutPdfFilePath);// 输出模板//读取 PDF 模板reader = new PdfReader(readPdfTemplateUrlOrPath);bos = new ByteArrayOutputStream();// 创建一个 PdfStamper 对象,用于修改 PDFstamper = new PdfStamper(reader, bos);// 获取 PDF 中的表单域AcroFields form = stamper.getAcroFields();//文字类的内容处理Map<String, String> textAreaMap = (Map<String, String>) areaMap.get("textAreaMap");if (Objects.nonNull(textAreaMap) && !textAreaMap.isEmpty()) {// 遍历表单数据,将数据填充到对应的表单域中for (Map.Entry<String, String> entry : textAreaMap.entrySet()) {String fieldName = entry.getKey();String fieldValue = entry.getValue();if (fieldName.startsWith("check")) {form.setField(fieldName, fieldValue, true);} else {form.setField(fieldName, fieldValue);}}}form.addSubstitutionFont(bf);//图片类的内容处理Map<String, String> imageAreaMap = (Map<String, String>) areaMap.get("imageAreaMap");if (Objects.nonNull(imageAreaMap) && !imageAreaMap.isEmpty()) {// 遍历表单数据,将数据填充到对应的表单域中for (Map.Entry<String, String> entry : imageAreaMap.entrySet()) {String fieldName = entry.getKey();String fieldValue = entry.getValue();List<AcroFields.FieldPosition> fieldPositions = form.getFieldPositions(fieldName);if (form.getFieldPositions(fieldName) != null) {int pageNo = fieldPositions.get(0).page;Rectangle signRect = fieldPositions.get(0).position;float x = signRect.getLeft();float y = signRect.getBottom();//根据路径读取图片Image image = Image.getInstance(fieldValue);//获取图片页面PdfContentByte under = stamper.getOverContent(pageNo);//图片大小自适应image.scaleToFit(signRect.getWidth(), signRect.getHeight());//添加图片image.setAbsolutePosition(x, y);under.addImage(image);}}}///*必须要调用这个,否则文档不会生成的  如果为false那么生成的PDF文件还能编辑,一定要设为true*/stamper.setFormFlattening(true);stamper.close();PdfCopy copy = new PdfCopy(doc, out);doc.open();for (int i = 1; i < reader.getNumberOfPages() + 1; i++) {doc.newPage();PdfImportedPage importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), i);copy.addPage(importPage);}doc.close();File file = new File(outPutPdfFilePath);log.info("pdf文件生成成功,文件路径为:" + file.getAbsolutePath());return file;} catch (Exception e) {log.error("pdf文件生成失败:", e);}return null;}public static PdfTemplateFillConfig getSystemType() {String os = System.getProperty("os.name").toLowerCase();if (os.contains("win")) {return PdfTemplateFillConfig.getWindowsInstance();} else if (os.contains("nix") || os.contains("nux") || os.contains("aix")) {return PdfTemplateFillConfig.getLinuxInstance();} else {log.error("未知操作系统,无法加载配置。os-{}", os);return null;}}
}
java">package com.example.excel.pdf;import lombok.Data;/*** @author: reshui* description:* DateTime:2025/2/28-15:48*/
@Data
public class PdfTemplateFillConfig {/*** 字体名*/private String fontName;/*** 编码*/private String encoding;/*** 是否嵌入字体* 该参数指定是否将字体嵌入到生成的 PDF 文件中。BaseFont.NOT_EMBEDDED 表示不嵌入字体,即生成的 PDF 文件不会包含字体文件本身,* 而是依赖于查看 PDF 的设备上是否安装了相应的字体。如果设置为 BaseFont.EMBEDDED,则会将字体文件嵌入到 PDF 中,确保在任何设备上都能正确显示字体,* 但会增加 PDF 文件的大小。*/private Boolean embedded;public static PdfTemplateFillConfig getLinuxInstance() {PdfTemplateFillConfig config = new PdfTemplateFillConfig();config.setFontName("STSong-Light");config.setEncoding("UniGB-UCS2-H");config.setEmbedded(true);return config;}public static PdfTemplateFillConfig getWindowsInstance() {PdfTemplateFillConfig config = new PdfTemplateFillConfig();config.setFontName("c://windows//fonts//simsunb.ttf");config.setEncoding("Identity-H");config.setEmbedded(true);return config;}
}

三、pdf模板效果

四、实现效果图

 


http://www.ppmy.cn/news/1576778.html

相关文章

RK3568平台(GPIO篇)libgpiod的使用

libgpiod 是一个用于与 Linux GPIO 子系统交互的用户空间库。它提供了一组简单的 API,允许开发者通过用户空间程序控制 GPIO 引脚,而无需编写内核模块。libgpiod 是替代旧的 sysfs GPIO 接口的推荐方式。 一.libgpiod 的基本概念 Chip:GPIO 控制器,通常对应 /dev/gpiochip…

Spring Cloud Alibaba学习 4- Spring Cloud Gateway入门使用

Spring Cloud Alibaba学习 4- Spring Cloud Gateway入门使用 中文文档Spring Cloud Gateway 中文文档 一. 基本使用 1. Predicate配置 1.1 配置参数介绍 直接通过官方给的application.yml介绍&#xff0c;这里就不介绍简写方式了&#xff0c;直接介绍完整方式 spring:clo…

react 19版中路由react-router-dom v7版的使用

路由的安装&#xff1a; npm install react-router-dom在src目录下建一个router文件夹 在router文件夹里面建一个index.tsx index.tsx内容&#xff1a; import React from react; import {BrowserRouter as Router,Routes,Route,Link } from react-router-dom; import ManuLi…

【AI+智造】人工智能的前世今生:从图灵测试到DeepSeek革命——如何用技术重构效率边界

作者&#xff1a;Odoo技术开发/资深信息化负责人 日期&#xff1a;2025年3月4日 引言&#xff1a;一场跨越半个世纪的认知革命 1950年&#xff0c;艾伦图灵提出了著名的“图灵测试”&#xff0c;开启了人类对机器智能的想象。70年后&#xff0c;AlphaGo击败围棋世界冠军李世石…

Linux : 环境变量

目录 一 环境变量 1.基本概念 二 常见环境变量 三 查看环境变量的方法 1.env:查看系统中所有环境变量 2. echo $NAME 四 如何不带路径也能运行的自己的程序 1.将自己的程序直接添加到PATH指定的路径下 五 环境变量与本地变量 1.本地变量 2. 环境变量 六C、C中main()…

Docker安装Prometheus监控平台

介绍 Prometheus是一个开源的系统监控和警报工具包&#xff0c;最初由 SoundCloud 开发并开源&#xff0c;现已成为云原生计算基金会&#xff08;CNCF&#xff09;的毕业项目。它广泛应用于监控基础设施、应用程序和服务的性能&#xff0c;并提供强大的数据查询和警报功能。许多…

浅谈开发基于DeepSeek的编程辅助插件需要系统性的技术规划和实施方案

开发基于DeepSeek的编程辅助插件需要系统性的技术规划&#xff0c;以下是分阶段实施方案&#xff0c;包含具体代码示例和技术细节&#xff1a; 一、技术准备阶段 1. 环境配置 # 开发环境建议 Node.js >18.x (VSCode插件) / JDK17 (IntelliJ插件) Python 3.10 (模型交互层…

AMD RDNA3 GPU架构解析

如果你对AMD的RDNA3还不了解&#xff0c;在profile过程中的指标无法完全理解一些指标&#xff0c;比如说你听过着色器性能方面指标"occupancy"&#xff0c;听说它有助于隐藏内存 latency&#xff0c;但不理解其中的具体用法&#xff0c;那这篇文章将对你有一些帮助。…