批量生成不同用户的pdf 文件(html样式)
技术 selenium + thymeleaf + itextpdf + chromedriver
使用thymeleaf 将动态数据替换
使用selenium +chromedriver 进行js ,css等逻辑运算后渲染视图
使用itextpdf 将html 转为pdf 文件
html模板
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>My Page</title><!-- 引入 jQuery 库 --><script src="https://code.jquery.com/jquery-3.6.0.min.js"></script><style>body {font-family: 'SimSun', 'SimHei', sans-serif;}</style><!-- 引入 G2 库 -->
<!-- <script src="https://gw.alipayobjects.com/os/lib/antv/g2/4.1.16/dist/g2.min.js"></script>-->
</head>
<body>
<h1 th:text="${title}">cser</h1>
<div id="content"></div>
<script type="text/javascript" th:inline="javascript">/*<![CDATA[*/document.addEventListener('DOMContentLoaded', function() {$('#content').html("<select name='status'>"+" <option value='测试'>111</option>"+" <option value='测试2'>222</option>"+"</select>")let titlenew = "测试"; // 确保这里赋值正确document.querySelector('h1').innerText = titlenew;document.title = titlenew; // 更新浏览器标签页的标题});/*]]>*/
</script></body>
</html>
执行代码
public void generatePdf(HttpServletResponse response) throws IOException {// 设置 ChromeDriver 路径// 设置 ChromeDriver 路径System.setProperty("webdriver.chrome.driver", "D:/chromedriver.exe");// 初始化 WebDriver// 设置chrome选项ChromeOptions options = new ChromeOptions();
// options.setBinary("D:\\chromedriver\\chrome/chrome.exe");options.setBinary("C:\\Chrome\\Application/chrome.exe");options.addArguments("--headless");options.addArguments("--disable-gpu");WebDriver driver = new ChromeDriver(options);// 动态数据Map<String, Object> data = new HashMap<>();data.put("title", "Hello, World!");data.put("condition", "true");
// data.put("imagePath", imagePath); // 路径// 使用 Thymeleaf 渲染模板Context context = new Context();context.setVariables(data);String htmlContent = templateEngine.process("templates", context);try {driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(60));// 将 htmlContent 进行 Base64 编码byte[] base64EncodedBytes = Base64.getEncoder().encode(htmlContent.getBytes(StandardCharsets.UTF_8));String base64EncodedHtmlContent = new String(base64EncodedBytes);// 构建完整的 data URLhtmlContent = "data:text/html;base64," + base64EncodedHtmlContent;// 加载HTML内容
// htmlContent = "data:text/html;charset=utf-8," + encodedHtmlContent;driver.get(htmlContent);// 等待JavaScript执行完成Thread.sleep(3000); // 等待3秒,确保JavaScript执行完成//获取全部的htmlString pageSource = driver.getPageSource();
// // 获取最终的HTML内容
// WebElement body = driver.findElement(By.tagName("html"));
// String renderedHtml = body.getAttribute("outerHTML");try (FileOutputStream outputStream = new FileOutputStream(filePath)) {// 使用字体文件路径创建字体对象String fontPath = "chromedriver/cs.TTF";FontProgram font = FontProgramFactory.createFont(fontPath);// 创建 DefaultFontProvider 并设置字体DefaultFontProvider fontProvider = new DefaultFontProvider(false, false, true);fontProvider.addFont(font);// 创建 ConverterProperties 并设置字体提供者ConverterProperties converterProperties = new ConverterProperties();converterProperties.setFontProvider(fontProvider);HtmlConverter.convertToPdf(pageSource, outputStream, converterProperties);} catch (Exception e) {e.printStackTrace();}} catch (InterruptedException e) {driver.close();}}
pom 依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency>
<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java --><dependency><groupId>org.seleniumhq.selenium</groupId><artifactId>selenium-java</artifactId><version>4.27.0</version></dependency><dependency><groupId>org.seleniumhq.selenium</groupId><artifactId>selenium-chrome-driver</artifactId><version>4.27.0</version> <!-- 确保与 selenium-java 版本一致 --></dependency><!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-remote-driver --><dependency><groupId>org.seleniumhq.selenium</groupId><artifactId>selenium-remote-driver</artifactId><version>4.27.0</version></dependency><!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-api --><dependency><groupId>org.seleniumhq.selenium</groupId><artifactId>selenium-api</artifactId><version>4.27.0</version></dependency><dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.11</version></dependency>
相关文章:
批量生成不同用户的pdf 文件(html样式)
技术 selenium thymeleaf itextpdf chromedriver 使用thymeleaf 将动态数据替换 使用selenium chromedriver 进行js ,css等逻辑运算后渲染视图 使用itextpdf 将html 转为pdf 文件 html模板 <!DOCTYPE html> <html xmlns:th"http://www.thymeleaf…...
混淆零碎知识点
minifyEnabled true //混淆开关 zipAlignEnabled true // Zipalign优化 shrinkResources true // 移除无用的resource文件 (必须要混淆开了之后才才可以设置为true) proguard-rules.pro 为混淆文件 //整个文件保留 不被混淆 -keep class com.cn…...
排序算法2
排序算法1-CSDN博客 排序算法1中提及的是较为基础(暴力实现,复杂度较高)的排序算法,不适合于数据量较大的场景,比如序列长度达到1e5 接下来以蓝桥另一道题目来理解其它的排序算法 蓝桥3226 蓝桥账户中心 样例 5 1 5 9 3 7 4、快速排序 快速排…...
【Web开发基础学习——corsheaders 应用的理解】
Web开发基础学习系列文章目录 第一章 基础知识学习之corsheaders 应用的理解 文章目录 Web开发基础学习系列文章目录前言一、使用1.1 安装1.2 配置 二、功能总结 前言 corsheaders 是一个 Django 第三方应用,用于处理跨域资源共享 (CORS)。CORS 是一种机制&#x…...
Redis和MySQL之间如何进行数据同步
原因 为什么要进行Redis和MySQL的数据同步? 性能优化:MySQL是关系型数据库,数据读取和存储相对复杂;Redis是内存数据库,读写速度极快,将热点数据存在Redis,可以大大提高系统的访问速度。 数据…...
css:转换
转换 移动 /* transform: translate(100px, 200px); */transform: translateX(100px);transform: translateY(100px); /*一个意思*/ 如果后面跟百分数的意思是移动盒子自身x/y方向长度的百分比,可以用作子绝父相控制盒子水平居中垂直居中 translate里的xy值是相对…...
状态管理与存储:Vuex 和 sessionStorage
1. sessionStorage 存储位置 sessionStorage 是浏览器提供的 Web Storage API 的一部分,用于在一个会话期间存储数据。数据保存在浏览器的 内存 中,而不是在硬盘上,且其生命周期仅限于当前浏览器标签页。数据在浏览器窗口或标签页关闭时会被…...
Redis和MySQL保持一致性的延迟双删(Delay Double Delete)策略
Redis和MySQL保持一致性的延迟双删(Delay Double Delete)策略,是一种在数据更新或删除时为了保证数据一致性而采取的方法。以下是延迟双删的过程和原理的详细解释: 一、过程 第一次删除缓存: 当需要更新数据库中的数据…...
快速理解微服务中Fegin的概念
一.由来 1.在传统的架构里面,我们是通过使用RestTemplate来访问其他的服务,但是这种方式就存在了一个很大的缺陷,也就是被调用方如果发生了服务的迁移(IP和端口发生了变化),那么调用方也需要同步的在代码里面进行修改,…...
新增工作台模块,任务中心支持一键重跑,MeterSphere开源持续测试工具v3.5版本发布
2024年11月28日,MeterSphere开源持续测试工具正式发布v3.5版本。 在这一版本中,MeterSphere新增工作台模块,工作台可以统一汇总系统数据,提升测试数据的可视化程度并增强对数据的分析能力,为管理者提供测试工作的全局…...
快速搭建一个博客!!!“Halo框架深度优化:搭建你的个性化博客或网站”
目录 引言: 一. 首先服务器上去下载一个docker 1.可以参考官方地址: 2. 通过宝塔来一键安装!!! 3.也可以自己下载!!! 1.卸载旧版 2.配置Docker的yum库 3.安装Docker 4.启动和…...
009 STM32 HAL库介绍
STM32 HAL库(Hardware Abstraction Layer)是STMicroelectronics为STM32系列微控制器提供的一套硬件抽象层库,它旨在简化STM32的开发过程,提高代码的可移植性和可维护性。HAL库通过提供一组统一的API接口,使得开发者无需…...
【微服务】 Eureka和Ribbon
一、Eureka 服务调用出现的问题:在远程调用另一个服务时,我们采用的解决办法是发送一次http请求,每次环境的变更会产生新的地址,所以采用硬编码会出现很多麻烦,并且为了应对并发问题,采用分布式部署&#…...
6.算法移植第六篇 YOLOV5/rknn生成可执行文件部署在RK3568上
接上一篇文章best-sim.rknn模型生成好后,我们要将其转换成可执行文件运行在RK3568上,这一步需要在rknpu上进行,在强调一遍!!rknpu的作用是可以直接生成在开发板上运行的程序 退出上一步的docker环境 exit1.复制best-…...
element的el-table表格标题用css自定义是否必填,用添加伪类的方式标红色*
element的el-table表格标题用css自定义是否必填添加伪类红色 * 效果图如下👇 el-table组件的html部分 css部分 /deep/.el-table__header-wrapper{.el-table__header{.has-gutter tr .el-table__cell:nth-of-type(3) .cell:before{content: *;color:red}.has-gutte…...
数据仓库: 8- 数据仓库性能优化
CSDN 目录展示 目录 8- 数据仓库性能优化8.1 查询优化8.1.1 索引优化8.1.2 分区和分桶8.1.3 使用缓存8.1.4 查询简化与重写8.1.5 聚合优化8.1.6 并行化和分布式计算8.1.7 基于列存储的优化8.1.8 表的分区和数据清洗8.1.9 查询提示 (Hints)8.1.10 自动调优工具 8.2 索引设计8.2…...
可编程网络在分布式深度学习通信瓶颈控制中的应用与未来展望
目录 可编程网络在分布式深度学习通信瓶颈控制中的应用与未来展望 可编程网络在分布式深度学习通信瓶颈控制中的应用与未来展望 在分布式深度学习领域,随着模型规模的不断扩大,训练过程中的通信开销已成为制约性能提升的关键因素。传统的分布式训练方法面临高通信延迟和带宽…...
【论文笔记】Tool Learning with Foundation Models 论文笔记
Tool Learning with Foundation Models 论文笔记 文章目录 Tool Learning with Foundation Models 论文笔记摘要背景:工作: 引言工具学习的发展本文工作(大纲&目录) 背景2.1 工具使用的认知起源2.2 工具分类:用户界…...
Springfox迁移到 Springdoc OpenAPI 3
将项目从 Springfox 迁移到 Springdoc OpenAPI 3 时,主要的工作是将原先使用的 Springfox 注解替换为 Springdoc OpenAPI 3 中的对应注解。虽然 Springdoc OpenAPI 3 基于 OpenAPI 3 规范,并且有一些不同的命名方式和设计理念,但大部分注解的…...
DIY-Tomcat part 3 实现对动态资源的请求
实现ServletRequest package connector;import javax.servlet.RequestDispatcher; import javax.servlet.ServletInputStream; import javax.servlet.ServletRequest; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.i…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...
springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...
Elastic 获得 AWS 教育 ISV 合作伙伴资质,进一步增强教育解决方案产品组合
作者:来自 Elastic Udayasimha Theepireddy (Uday), Brian Bergholm, Marianna Jonsdottir 通过搜索 AI 和云创新推动教育领域的数字化转型。 我们非常高兴地宣布,Elastic 已获得 AWS 教育 ISV 合作伙伴资质。这一重要认证表明,Elastic 作为 …...
使用SSE解决获取状态不一致问题
使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件,这个上传文件是整体功能的一部分,文件在上传的过程中…...
密码学基础——SM4算法
博客主页:christine-rr-CSDN博客 专栏主页:密码学 📌 【今日更新】📌 对称密码算法——SM4 目录 一、国密SM系列算法概述 二、SM4算法 2.1算法背景 2.2算法特点 2.3 基本部件 2.3.1 S盒 2.3.2 非线性变换 编辑…...
如何把工业通信协议转换成http websocket
1.现状 工业通信协议多数工作在边缘设备上,比如:PLC、IOT盒子等。上层业务系统需要根据不同的工业协议做对应开发,当设备上用的是modbus从站时,采集设备数据需要开发modbus主站;当设备上用的是西门子PN协议时…...
用js实现常见排序算法
以下是几种常见排序算法的 JS实现,包括选择排序、冒泡排序、插入排序、快速排序和归并排序,以及每种算法的特点和复杂度分析 1. 选择排序(Selection Sort) 核心思想:每次从未排序部分选择最小元素,与未排…...
持续交付的进化:从DevOps到AI驱动的IT新动能
文章目录 一、持续交付的本质:从手动到自动的交付飞跃关键特性案例:电商平台的高效部署 二、持续交付的演进:从CI到AI驱动的未来发展历程 中国…...
