Java-實現PDF合同模板填寫內容并導出PDF文件

可用于公司用戶合同導出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>

二、工具類代碼實現

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;}}
}
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.pswp.cn/bicheng/72596.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/72596.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/72596.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【人工智能】GPT-4 vs DeepSeek-R1:誰主導了2025年的AI技術競爭?

前言 2025年&#xff0c;人工智能技術將迎來更加激烈的競爭。隨著OpenAI的GPT-4和中國初創公司DeepSeek的DeepSeek-R1在全球范圍內嶄露頭角&#xff0c;AI技術的競爭格局開始發生變化。這篇文章將詳細對比這兩款AI模型&#xff0c;從技術背景、應用領域、性能、成本效益等多個方…

前端開發10大框架深度解析

摘要 在現代前端開發中&#xff0c;框架的選擇對項目的成功至關重要。本文旨在為開發者提供一份全面的前端框架指南&#xff0c;涵蓋 React、Vue.js、Angular、Svelte、Ember.js、Preact、Backbone.js、Next.js、Nuxt.js 和 Gatsby。我們將從 簡介、優缺點、適用場景 以及 實際…

【MySQL】索引(頁目錄、B+樹)

文章目錄 1. 引入索引2. MySQL與磁盤交互的基本單位3. 索引的理解3.1 頁目錄3.2 B樹 4. 聚簇索引、非聚簇索引5. 索引的操作5.1 索引的創建5.1.1 創建主鍵索引5.1.2 創建唯一索引5.1.3 普通索引的創建5.1.4 全文索引的創建 5.2 索引的查詢5.3 刪除索引 1. 引入索引 索引&#…

python-串口助手(OV7670圖傳)

代碼 主python文件 import serial import serial.tools.list_ports import time import tkinter as tk from tkinter import ttk import numpy as np from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from matplotlib.figure import Figure import threadi…

筑牢網絡安全防線:守護您的數據安全

在數字化時代&#xff0c;數據安全已成為企業和個人不容忽視的重要議題。近日印尼國家數據中心遭黑客襲擊的事件&#xff0c;不僅擾亂了機場的移民檢查&#xff0c;還影響了眾多機構的服務運行。黑客利用惡意軟件對數據中心進行攻擊&#xff0c;索要巨額贖金&#xff0c;給印尼…

Vue 3 整合 WangEditor 富文本編輯器:從基礎到高級實踐

本文將詳細介紹如何在 Vue 3 項目中集成 WangEditor 富文本編輯器&#xff0c;實現圖文混排、自定義擴展等高階功能。 一、為什么選擇 WangEditor&#xff1f; 作為國內流行的開源富文本編輯器&#xff0c;WangEditor 具有以下優勢&#xff1a; 輕量高效&#xff1a;壓縮后僅…

FastGPT 引申:信息抽取到知識圖譜的銜接流程

文章目錄 信息抽取到知識圖譜的銜接流程步驟1&#xff1a;原始信息抽取結果步驟2&#xff1a;數據標準化處理&#xff08;Python示例&#xff09;步驟3&#xff1a;Cypher代碼動態生成&#xff08;Python驅動&#xff09; 關鍵銜接邏輯說明1. 唯一標識符生成規則2. 數據映射策略…

Webshell 入侵與防御全攻略

Webshell&#xff0c;是指攻擊者上傳到網站的遠程控制后門&#xff0c;允許黑客像管理員一樣遠程控制網站&#xff0c;執行惡意命令&#xff0c;甚至完全接管網站。本文將帶你深入了解 Webshell 的入侵方式以及相應的防御措施&#xff0c;幫助你加固自己的網站防線。 什么是 W…

NL2SQL-基于Dify+阿里通義千問大模型,實現自然語音自動生產SQL語句

本文基于Dify阿里通義千問大模型&#xff0c;實現自然語音自動生產SQL語句功能&#xff0c;話不多說直接上效果圖 我們可以試著問他幾個問題 查詢每個部門的員工數量SELECT d.dept_name, COUNT(e.emp_no) AS employee_count FROM employees e JOIN dept_emp de ON e.emp_no d…

雙鏈路提升網絡傳輸的可靠性擴展可用帶寬

為了提升網絡傳輸的可靠性或增加網絡可用帶寬&#xff0c; 通常使用雙鏈路冗余備份或者雙鏈路聚合的方式。 本文介紹幾種雙鏈路網絡通信的案例。 5GWiFi冗余傳輸 雙Socket綁定不同網絡接口&#xff1a;通過Android的ConnectivityManager綁定5G蜂窩網絡和WiFi的Socket連接&…

Ubuntu22.04安裝Ollama部署DeepSeek-R1:32B模型

一、環境準備 1.硬件要求 GPU: 至少 NVIDIA A30/A100 (顯存 ≥ 24GB)內存: ≥ 64GB RAM存儲: ≥ 100GB 可用空間 (模型文件約 60GB)2.軟件依賴 # 驗證NVIDIA驅動 nvidia-smi二、Ollama安裝 方法 1:install.sh安裝 運行一下安裝命令: curl -fsSL https://ollama.com/inst…

LeetCode 解題思路 10(Hot 100)

解題思路&#xff1a; 上邊&#xff1a; 從左到右遍歷頂行&#xff0c;完成后上邊界下移&#xff08;top&#xff09;。右邊&#xff1a; 從上到下遍歷右列&#xff0c;完成后右邊界左移&#xff08;right–&#xff09;。下邊&#xff1a; 從右到左遍歷底行&#xff0c;完成后…

Checkpoint 模型與Stable Diffusion XL(SDXL)模型的區別

Checkpoint 模型與 Stable Diffusion XL&#xff08;SDXL&#xff09;模型 在功能、架構和應用場景上有顯著區別&#xff0c;以下是主要差異的總結&#xff1a; 1. 基礎架構與定位 Checkpoint 模型 是基于 Stable Diffusion 官方基礎模型&#xff08;如 SD 1.4/1.5&#xff09;…

GCC RISCV 后端 -- C語言語法分析過程

在 GCC 編譯一個 C 源代碼時&#xff0c;先會通過宏處理&#xff0c;形成 一個叫轉譯單元&#xff08;translation_unit&#xff09;&#xff0c;接著進行語法分析&#xff0c;C 的語法分析入口是 static void c_parser_translation_unit(c_parser *parser); 接著就通過類似遞…

第十五屆藍橋杯Scratch12月stema選拔賽真題—消失的水母

消失的水母 編程實現&#xff1a; 消失的水母。&#xff08;角色、背景非源素材&#xff09; 具體要求&#xff1a; 1、每次點擊綠旗&#xff0c;水母說“請輸入 2&#xff5e;10 的整數”&#xff0c;同時在舞臺下方顯示輸入框&#xff0c;如圖所示; 完整題目可點擊下方鏈…

Redis設計與實現-數據結構

Redis數據結構 1、RedisObject對象2、簡單動態字符串2.1 SDS定義2.2 SDS與C語言的區別2.3 SDS的空間分配策略2.3.1 空間預分配2.3.2 惰性空間釋放 2.4 SDS的API 3、鏈表3.1 鏈表的定義3.2 鏈表的API 4、字典4.1 字典的定義4.2 哈希算法4.3 哈希表的擴縮4.3.1 哈希表擴縮的判斷依…

由麻省理工學院計算機科學與人工智能實驗室等機構創建低成本、高效率的物理驅動數據生成框架,助力接觸豐富的機器人操作任務

2025-02-28&#xff0c;由麻省理工學院計算機科學與人工智能實驗室&#xff08;CSAIL&#xff09;和機器人與人工智能研究所的研究團隊創建了一種低成本的數據生成框架&#xff0c;通過結合物理模擬、人類演示和基于模型的規劃&#xff0c;高效生成大規模、高質量的接觸豐富型機…

RK3588開發筆記-fiq_debugger: cpu 0 not responding, reverting to cpu 3問題解決

目錄 前言 一、FIQ Debugger介紹 二、rockchip平臺配置方法 三、問題分析定位 IRQF_NOBALANCING 的含義 總結 前言 在進行 RK3588 開發的過程中,我們可能會遇到各種棘手的問題。其中,“fiq_debugger: cpu 0 not responding, reverting to cpu 3” 這個錯誤出現在RK3588的…

計算機視覺|ViT詳解:打破視覺與語言界限

一、ViT 的誕生背景 在計算機視覺領域的發展中&#xff0c;卷積神經網絡&#xff08;CNN&#xff09;一直占據重要地位。自 2012 年 AlexNet 在 ImageNet 大賽中取得優異成績后&#xff0c;CNN 在圖像分類任務中顯示出強大能力。隨后&#xff0c;VGG、ResNet 等深度網絡架構不…

SpringTask 引起的錯誤

SpringTask 引起的錯誤 1. 場景 在使用 SpringBoot 編寫后臺程序時&#xff0c;當在瀏覽器頁面中發起請求時&#xff0c;MP 自動填充來完成一些字段的填充&#xff0c;例如創建時間、創建人、更新時間、更新人等。但是當編寫微信小程序時&#xff0c;由于一些字段無法進行自動…