SpringBoot集成 itextpdf 根据模板动态生成PDF

目录

  • 需求说明
  • 前期准备
  • Spring Boot 集成
    • 添加依赖
    • 构建工具类
    • 构建MultipartFile
    • 编辑PDF模板
    • Java代码设置对应form的key-value

需求说明

根据合同模板,将动态的合同标签,合同方以及合同签约时间等动态的生成PDF,供用户下载打印。

前期准备

安装 Adobe Acrobat DC
链接:https://pan.baidu.com/s/1xkIioIBDG4uLBGP20SZJEA
提取码:yn8g

Spring Boot 集成

添加依赖

        <dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.9</version><scope>compile</scope></dependency><!--中文问题解决--><dependency><groupId>com.itextpdf</groupId><artifactId>itext-asian</artifactId><version>5.2.0</version></dependency>

构建工具类

public class PDFUtils {private static final Logger log = LoggerFactory.getLogger(PDFUtils.class);/*** 根据pdf模板输出流* @param templateFileName 模板文件名* @param resultMap 包含文件字段名和值的map* @return 生成的文件字节流*/public static ByteArrayOutputStream createPdfStream(String templateFileName,Map<String, String> resultMap){ByteArrayOutputStream ba = new ByteArrayOutputStream();PdfStamper stamp =null;PdfReader reader = null;try {reader = new PdfReader(templateFileName);stamp = new PdfStamper(reader, ba);//使用字体BaseFont bf = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);/* 获取模版中的字段 */AcroFields form = stamp.getAcroFields();//填充表单if (resultMap != null) {for (Map.Entry<String, String> entry : resultMap.entrySet()) {form.setFieldProperty(entry.getKey(), "textfont", bf, null);form.setField(entry.getKey(), entry.getValue()!=null?entry.getValue():"");}}//不能编辑stamp.setFormFlattening(true);} catch (IOException e) {log.error("文档构建I/O异常",e);} catch (DocumentException e) {log.error("文档构建异常",e);}finally {if(stamp!=null){try {stamp.close();} catch (DocumentException e) {log.error("流关闭错误",e);} catch (IOException e) {log.error("流关闭错误",e);}}if(reader!=null){reader.close();}}return ba;}
}

构建MultipartFile

方便之后上传OSS返回url

public UploadFileModel createUrl(String filePath, ByteArrayOutputStream byteArrayOutputStream) throws URISyntaxException {try{byte[] pdfBytes = byteArrayOutputStream.toByteArray();MultipartFile multipartFile = new MockMultipartFile("file",filePath,"application/pdf",pdfBytes);return uploadFileUtil.upload(multipartFile);} catch (Exception e) {log.error("创建Url时出错:" + e.getMessage());}return null;}

编辑PDF模板

在这里插入图片描述
在这里插入图片描述

Java代码设置对应form的key-value

pdf模板放在springboot 项目目录resources/static 目录下

 public String createContract(CreateContractRequest request) {HashMap<String, String> map = new HashMap<>();map.put("companyName",request.getCompanyName());map.put("phone",request.getPhone());UploadFileModel url = null;ByteArrayOutputStream pdfStream = PDFUtils.createPdfStream(UserApplication.class.getResource("/").getPath() + "static/contract.pdf", map);try {url = createUrl("合同.pdf", pdfStream);} catch (URISyntaxException e) {throw new RuntimeException(e);}return url.getUrl();}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/775370.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux学习_进程

1.进程 概念&#xff1a;程序的一个执行实例&#xff0c;正在执行的程序等&#xff0c;担当分配系统资源&#xff08;CPU时间&#xff0c;内存&#xff09;的实体&#xff0c;进程PCB自己的代码和数据 PCB&#xff1a;进程信息被放在一个叫做进程控制块的数据结构中&#xff…

左手医生:医疗 AI 企业的云原生提效降本之路

相信这样的经历对很多人来说并不陌生&#xff1a;为了能到更好的医院治病&#xff0c;不惜路途遥远奔波到大城市&#xff1b;或者只是看个小病&#xff0c;也得排上半天长队。这些由于医疗资源分配不均导致的就医问题已是老生长谈。 云计算、人工智能、大数据等技术的发展和融…

LLMs之Grok-1:model.py文件解读—实现了基于Transformer的预训练语言模型+利用JAX框架支持高性能分布式计算

LLMs之Grok-1:model.py文件解读—实现了基于Transformer的预训练语言模型+利用JAX框架支持高性能分布式计算 目录 model.py文件解读—实现了基于Transformer的预训练语言模型+利用JAX框架支持高性能分布式计算

【嵌入式——C语言】VScode编写C程序、交叉编译

【嵌入式——C语言】VScode编写C程序、交叉编译 第一步第二步第三步第四步第五步第六步第七步第八步 第一步 下载Visual Studio Code下载地址 然后直接安装就可以了。 第二步 前提是你的电脑上安装了WSL。。。 打开vscode的扩展&#xff0c;输入WSL进行安装 安装完之后在窗…

装饰器模式实战运用(功能增强)

目录 前言 装饰器模式与代理模式的区别 UML plantuml 类图 实战代码 mybatis cache 前言 装饰器模式和代理模式在使用上很相似&#xff0c;都是在不修改原始类代码的情况下&#xff0c;动态地给真实对象的方法做增强。 装饰器模式是通过创建一个包装对象来包裹原有对象…

HuggingFace: 掌握自然语言处理的利器

引言 在当今人工智能领域中&#xff0c;自然语言处理&#xff08;NLP&#xff09;一直是备受关注的焦点之一。从智能助手到情感分析&#xff0c;NLP技术已经深入到我们日常生活和工作的方方面面。然而&#xff0c;随着数据量的增长和模型复杂性的提升&#xff0c;开发和部署高…

c# RichTextbox添加行号

使用另一个RichTextBox放在要添加行号的左边 使用以下代码 //uiRichTextBox1为右侧文本框&#xff0c;uiRichTextBox2为左侧文本框int lineIndex 0;private void uiRichTextBox1_TextChanged(object sender, EventArgs e){if (lineIndex > uiRichTextBox1.Lines.Length){L…

C++之STL整理(1)之vector、map数据结构初识

C之STL整理&#xff08;1&#xff09;之vector、map数据结构初识 注&#xff1a;整理一些突然学到的C知识&#xff0c;随时mark一下 例如&#xff1a;忘记的关键字用法&#xff0c;新关键字&#xff0c;新数据结构 C 的 STL C之STL整理&#xff08;1&#xff09;之vector、map数…

腾讯云4核8G12M云服务器一年646元,送3个月时长

2024年腾讯云4核8G服务器租用优惠价格&#xff1a;轻量应用服务器4核8G12M带宽646元15个月&#xff0c;CVM云服务器S5实例优惠价格1437.24元买一年送3个月&#xff0c;腾讯云4核8G服务器活动页面 txybk.com/go/txy 活动链接打开如下图&#xff1a; 腾讯云4核8G服务器优惠价格 轻…

《每天十分钟》-红宝书第4版-对象、类与面向对象编程(六)

盗用构造函数 上节提到原型包含引用值导致的继承问题&#xff0c;为了解决这种问题&#xff0c;一种叫作“盗用构造函数”&#xff08;constructor stealing&#xff09;的技术在开发社区流行起来&#xff08;这种技术有时也称作“对象伪装”或“经典继承”&#xff09;。基本…

若依 3.8.7版本springboot前后端分离 整合mabatis plus

1.去掉mybatis 这一步我没有操作&#xff0c;看别人的博客有说不去掉可能冲突&#xff0c;也可能不冲突&#xff0c;我试下来就没去掉如需要去除&#xff0c;到总的pom.xml中properties标签下的<mybatis-spring-boot.version>x.x.x</mybatis-spring-boot.version>…

C++ pdf 打印 插入图片

一&#xff1a;使用PODOFO给PDF插入图片&#xff1a; #include <podofo.h> int main() { PoDoFo::PdfMemDocument pdfDocument; PoDoFo::PdfPage* page; PoDoFo::PdfImage image; PoDoFo::PdfVecObjects* vec_objects; PoDoFo::PdfRect rect; …

Kotlin by关键字

委托的概念 委托是一种设计模式,它的基本概念是:操作对象自己不会去处理某段逻辑,而是会把工作委托给另外一个辅助对象去处理。 class NewList<out T>(private val list: MutableList<T>) {fun isEmpty() = list.isEmpty()fun add(item: @UnsafeVariance T) = l…

iPad Pro安装Code APP结合内网穿透实现公网SSH远程连接服务器云开发

文章目录 1. 在iPad下载Code APP2.安装cpolar内网穿透2.1 cpolar 安装2.2 创建TCP隧道 3. iPad远程vscode4. 配置固定TCP端口地址4.1 保留固定TCP地址4.2 配置固定的TCP端口地址4.3 使用固定TCP地址远程vscode 本文主要介绍开源iPad应用IDE Code App 如何下载安装&#xff0c;并…

零基础Web3入门到精通

Web3 是互联网的下一代&#xff0c;它将使人们能够拥有自己的数据并控制自己的在线体验。Web3 基于区块链技术&#xff0c;该技术为安全、透明和可信的交易提供支持。 现在的web已被成为传统互联网了&#xff0c;那么如何抓住下一代互联网的红利呢&#xff0c;有没有想一起学习…

react 简单的demo

实现些简单的deomo 显示时间 自定义hooks 使用定时器、生命周期、通过状态渲染更新 // hooks 文件 import { useEffect, useState } from reactfunction getDate() {let date new Date();let year date.getFullYear()let hour date.getHours();let minutes date.getMinut…

爬虫requests.get中的参数

requests.get 是 Python 中 requests 库的一个方法&#xff0c;用于发送 GET 请求。它有许多参数可以配置&#xff0c;以下是一些常见的参数&#xff1a; url&#xff1a;指定要发送 GET 请求的 URL。params&#xff1a;可选参数&#xff0c;用于向请求添加 URL 参数。data&…

多线程基础:线程创建、同步与通信——学习指南

多线程基础&#xff1a;线程创建、同步与通信——学习指南 文章目录 多线程基础&#xff1a;线程创建、同步与通信——学习指南前言一、线程创建1、原理2、案例3、使用场景推荐 二、线程同步1、原理2、案例1&#xff09;synchronized关键字1.1&#xff09;修饰实例方法&#xf…

qt-C++笔记之QSpinBox控件

qt-C笔记之QSpinBox控件 code review! 文章目录 qt-C笔记之QSpinBox控件1.运行2.main.cpp3.main.pro4.《Qt6 C开发指南》&#xff1a;4.4 QSpinBox 和QDoubleSpinBox 1.运行 2.main.cpp #include <QApplication> #include <QSpinBox> #include <QPushButton&g…

Vue3 实现基于token 用户登录

前后端分离情况下&#xff0c;实现的大致思路 1 第一次登录的时候&#xff0c;前端调用后端的登录接口&#xff0c;发送用户名与密码 2 后端收到请求&#xff0c;验证用户名和密码&#xff0c;验证成功 给前端返回一个token 3 前段拿到token 将token 存储进localStorage 和…