Java实现HTML转PDF(deepSeekAi->html->pdf)

Java实现HTML转PDF,主要为了解决将ai返回的html文本数据转为PDF文件方便用户下载查看。

一、deepSeek-AI提问词

基于以上个人数据。总结个人身体信息,分析个人身体指标信息。再按一个月为维度,详细列举一个月内训练计划,维度详细至每周每天,要求:不可省略表格内容以精简示例,文本结构顺序为标题个人信息,第一步,第二步。最终回答结果以标准的html形式返回结果,不能带有meta标签,字体为STSong-Light,SimSun,html内容禁止使用单标签。

二、表设计

CREATE TABLE `p_deep_seek_task` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '任务id',`user_id` bigint(20) NOT NULL COMMENT '用户id',`status` char(2) NOT NULL DEFAULT '0' COMMENT '任务状态(0:待处理,1:处理中,2:处理成功,3:异常处理失败,4:重试中,5:重试失败)',`try_time` int(11) NOT NULL DEFAULT '0' COMMENT '执行次数',`result_url` varchar(255) DEFAULT NULL COMMENT '结果文件url',`prompt` longtext NOT NULL COMMENT '提问内容',`content` longtext COMMENT '结果内容',`reasoning_content` longtext COMMENT '思考过程',`create_time` datetime DEFAULT NULL COMMENT '创建时间',`create_by` bigint(20) DEFAULT NULL COMMENT '创建人',`update_by` bigint(20) DEFAULT NULL COMMENT '更新人',`update_time` datetime DEFAULT NULL COMMENT '更新时间',`task_time` date DEFAULT NULL COMMENT '任务日期',`execute_time` datetime DEFAULT NULL COMMENT '执行时间',`exception_msg` longtext COMMENT '异常信息',`cost_time` bigint(20) NOT NULL DEFAULT '0' COMMENT '执行耗时(s)'PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8mb4 COMMENT='deepseek任务';

三、导入Jar包

        <dependency><groupId>io.github.pig-mesh.ai</groupId><artifactId>deepseek-spring-boot-starter</artifactId></dependency><dependency><groupId>org.xhtmlrenderer</groupId><artifactId>flying-saucer-pdf</artifactId><version>9.1.22</version> </dependency><dependency><groupId>org.jsoup</groupId><artifactId>jsoup</artifactId><version>1.14.3</version> </dependency>

四、工具类

ai请求工具

package com.company.project.service.client;import io.github.pigmesh.ai.deepseek.config.DeepSeekProperties;
import io.github.pigmesh.ai.deepseek.core.DeepSeekClient;
import io.github.pigmesh.ai.deepseek.core.chat.ChatCompletionRequest;
import io.github.pigmesh.ai.deepseek.core.chat.ChatCompletionResponse;
import org.springframework.stereotype.Service;import javax.annotation.Resource;/*** @author: reshui* description:DeepSeek服务* DateTime:2025/3/31-14:48*/
@Service
public class DeepSeekAiClient {@Resourceprivate DeepSeekClient deepSeekClient;@Resourceprivate DeepSeekProperties deepSeekProperties;/*** 提问接口* 获取deepseek的响应结果* @param prompt 提示词*/public ChatCompletionResponse syncChat(String prompt) {ChatCompletionRequest request = ChatCompletionRequest.builder()// 根据渠道模型名称动态修改这个参数.model(deepSeekProperties.getModel()).addUserMessage(prompt).build();return deepSeekClient.chatCompletion(request).execute();}}
  1. 特定html字符内容过滤工具

package com.company.project.service.tools;import cn.hutool.core.collection.CollUtil;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;import java.util.regex.Matcher;
import java.util.regex.Pattern;/*** @author reshui* description* dateTime 2025/04/17*/
public class HtmlFormatter {private String htmlContent;private HtmlFormatter(String htmlContent) {this.htmlContent = htmlContent;}// 入口方法,创建处理器实例public static HtmlFormatter process(String htmlContent) {return new HtmlFormatter(htmlContent);}// 链式方法:前置过滤干扰字符public HtmlFormatter beforeFilter() {this.htmlContent = beforeFilterInterferenceCharacters(this.htmlContent);return this;}// 链式方法:替换内容标签public HtmlFormatter replaceTags() {this.htmlContent = replaceContentTag(this.htmlContent);return this;}// 链式方法:后置过滤干扰字符public HtmlFormatter afterFilter() {this.htmlContent = afterFilterInterferenceCharacters(this.htmlContent);return this;}// 获取最终结果public String get() {return this.htmlContent;}public static String formatHtml(String htmlContent) {// 过滤掉html中的干扰字符String filteredHtml = beforeFilterInterferenceCharacters(htmlContent);// 去除内容中的大于小于号干扰String replaceContentTag = replaceContentTag(filteredHtml);//过滤html中的干扰标签return afterFilterInterferenceCharacters(replaceContentTag);}/*** 替换html中的干扰内容** @param html 文本*/public static String replaceContentTag(String html) {Document doc = Jsoup.parse(html);removeTag(doc);traverse(doc.body());doc.outputSettings().prettyPrint(false);return doc.html();}/*** 去除不支持的meta标签* @param doc jsoupdoc*/public static void removeTag(Document doc) {Elements meta = doc.getElementsByTag("meta");for (Element metaElement : meta) {metaElement.remove();}}public static void traverse(Element element) {if (CollUtil.isEmpty(element.children())) {String text = element.text().replace("<", "小于").replace(">", "大于");element.text(text);}for (Element child : element.children()) { // 遍历子元素traverse(child); // 递归调用以处理子元素及其子元素}}/*** 后置过滤掉html中的干扰字符** @param html 文本*/public static String afterFilterInterferenceCharacters(String html) {return html.replace("<br></br>", "<br/>").replace("<br>", "<br/>").replace("</br>", "<br/>");}/*** 前置过滤掉html中的干扰字符** @param html 文本*/public static String beforeFilterInterferenceCharacters(String html) {return html.replace("```html", "").replace("```", "").replace("<!DOCTYPE html>", "").replace("<!doctype html>", "");}/*** 将HTML字符串中的所有标签转为小写** @param html 原始HTML字符串* @return 转换后的HTML字符串*/public static String convertTagsToLowerCase(String html) {// 正则表达式匹配HTML标签Pattern pattern = Pattern.compile("</?\\w+((\\s+\\w+(\\s*=\\s*(?:\".*?\"|'.*?'|[^'\">\\s]+))?)+\\s*|\\s*)/?>");Matcher matcher = pattern.matcher(html);StringBuffer result = new StringBuffer();while (matcher.find()) {// 将匹配到的标签转为小写String lowerCaseTag = matcher.group().toLowerCase();matcher.appendReplacement(result, lowerCaseTag);}matcher.appendTail(result);return result.toString();}}
  1. html转pdf工具

package com.company.project.service.tools;import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import com.company.project.common.utils.SpringUtils;
import com.company.project.service.properties.PdfFontProperties;
import lombok.extern.slf4j.Slf4j;
import org.xhtmlrenderer.pdf.ITextRenderer;import java.io.File;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Date;/*** @author: reshui* description: html转pdf工具类* DateTime:2025/3/31-15:55*/
@Slf4j
public class HtmlToPdfTools {/*** 文件暂存地址*/private static final String TEMP_FILE_PATH = System.getProperty("java.io.tmpdir");/*** pdf文件暂存地址*/private static final String PDF_FILE_PATH = TEMP_FILE_PATH + File.separator + "ai_train_pdf";/*** 时间格式*/private static final String TIMESTAMP_FORMAT = "yyyyMMddHHmmss";/*** pdf配置文件*/public final static PdfFontProperties CONFIG = SpringUtils.getBean(PdfFontProperties.class);/*** html转pdf文件** @param htmlContent html内容文本*/public static File convertHtmlToPdfFile(String htmlContent) throws Exception {String formatDateTimeStamp = DateUtil.format(new Date(), TIMESTAMP_FORMAT);String pdfFilePath = PDF_FILE_PATH + File.separator + formatDateTimeStamp + ".pdf";FileUtil.touch(pdfFilePath);String resultHtmlContent = HtmlFormatter.process(htmlContent).beforeFilter().replaceTags().afterFilter().get();generatePdfReport(pdfFilePath, resultHtmlContent);log.info("pdf文件储存地址:{}", pdfFilePath);return new File(pdfFilePath);}/*** 生成pdf文件** @param outputPath  输出文件地址* @param htmlContent html内容文本*/public static void generatePdfReport(String outputPath, String htmlContent) throws Exception {try (OutputStream outputStream = Files.newOutputStream(Paths.get(outputPath))) {ITextRenderer renderer = new ITextRenderer();renderer.getFontResolver().addFont(CONFIG.getPath(),CONFIG.getEncoding(),CONFIG.getEmbedded());
//            renderer.getFontResolver().addFont(
//                    "c://Windows//Fonts//simsun.ttc",
//                    "Identity-H",
//                    true
//            );renderer.setDocumentFromString(htmlContent);renderer.layout();renderer.createPDF(outputStream);}}public static void main(String[] args) throws Exception {String html = "";convertHtmlToPdfFile(html);}
}

配置文件yml

# deepseek配置文件
deepseek:base-url: https://api.deepseek.com/v1api-key: xxxxxxxxxxxxxmodel: deepseek-reasonerconnectTimeout: 60readTimeout: 240callTimeout: 360# windows-pdf字体配置
pdf:font:path: c://Windows//Fonts//simsun.ttcencoding: Identity-Hembedded: true# linux-pdf字体配置
pdf:font:path: c://Windows//Fonts//simsun.ttcencoding: Identity-Hembedded: true

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

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

相关文章

Estimands与Intercurrent Events:临床试验与统计学核心框架

1. Estimands(估计目标)概述 1.1 定义与作用 1.1.1 定义 Estimand是临床试验中需明确提出的科学问题,即研究者希望通过数据估计的“目标量”,定义“治疗效应”具体含义,确保分析结果与临床问题一致。 例如,在研究某种新药对高血压患者降压效果时,Estimand可定义为“在…

Jsp技术入门指南【十】IDEA 开发环境下实现 MySQL 数据在 JSP 页面的可视化展示,实现前后端交互

Jsp技术入门指南【十】IDEA 开发环境下实现 MySQL 数据在 JSP 页面的可视化展示&#xff0c;实现前后端交互 前言一、JDBC 核心接口和类&#xff1a;数据库连接的“工具箱”1. 常用的 2 个“关键类”2. 必须掌握的 5 个“核心接口” 二、创建 JDBC 程序的步骤1. 第一步&#xf…

深入理解HotSpot JVM 基本原理

关于JAVA Java编程语言是一种通用的、并发的、面向对象的语言。它的语法类似于C和C++,但它省略了许多使C和C++复杂、混乱和不安全的特性。 Java 是几乎所有类型的网络应用程序的基础,也是开发和提供嵌入式和移动应用程序、游戏、基于 Web 的内容和企业软件的全球标准。. 从…

【HTTP/3:互联网通信的量子飞跃】

HTTP/3&#xff1a;互联网通信的量子飞跃 如果说HTTP/1.1是乡村公路&#xff0c;HTTP/2是现代高速公路系统&#xff0c;那么HTTP/3就像是一种革命性的"传送门"技术&#xff0c;它彻底重写了数据传输的底层规则&#xff0c;让信息几乎可以瞬间抵达目的地&#xff0c;…

Apipost免费版、企业版和私有化部署详解

Apipost是企业级的 API 研发协作一体化平台&#xff0c;为企业提供 API研发测试管理全链路解决方案&#xff0c;不止于API研发场景&#xff0c;增强企业API资产管理。 Apipost 基于同一份数据源&#xff0c;同时提供给后端开发、前端开发、测试人员使用的接口调试、Mock、自动化…

使用若依二次开发商城系统-1:搭建若依运行环境

前言 若依框架有很多版本&#xff0c;这里使用的是springboot3vue3这样的一个前后端分离的版本。 一.操作步骤 1 下载springboot3版本的后端代码 后端springboot3的代码路径&#xff0c;https://gitee.com/y_project/RuoYi-Vue 需要注意我们要的是springboot3分支。 先用g…

速成GO访问sql,个人笔记

更多个人笔记&#xff1a;&#xff08;仅供参考&#xff0c;非盈利&#xff09; gitee&#xff1a; https://gitee.com/harryhack/it_note github&#xff1a; https://github.com/ZHLOVEYY/IT_note 本文是基于原生的库 database/sql进行初步学习 基于ORM等更多操作可以关注我…

【C++指南】告别C字符串陷阱:如何实现封装string?

&#x1f31f; 各位看官好&#xff0c;我是egoist2023&#xff01; &#x1f30d; 种一棵树最好是十年前&#xff0c;其次是现在&#xff01; &#x1f4ac; 注意&#xff1a;本章节只详讲string中常用接口及实现&#xff0c;有其他需求查阅文档介绍。 &#x1f680; 今天通过了…

系统架构师2025年论文《论软件架构评估2》

论软件系统架构评估 v2.0 摘要: 某市医院预约挂号系统建设推广应用项目是我市卫生健康委员会 2019 年发起的一项医疗卫生行业便民惠民信息化项目,目的是实现辖区内患者在辖区各公立医疗机构就诊时,可以通过多种线上渠道进行预约挂号,提升就医体验。我作为系统架构师参与此…

BEVDet4D: Exploit Temporal Cues in Multi-camera 3D Object Detection

背景 对于现有的BEVDet方法,它对于速度的预测误差要高于基于点云的方法,对于像速度这种与时间有关的属性,仅靠单帧数据很难预测好。因此本文提出了BEVDet4D,旨在获取时间维度上的丰富信息。它是在BEVDet的基础上进行拓展,保留了之前帧的BEV特征,并将其进行空间对齐后与当…

el-upload 上传逻辑和ui解耦,上传七牛

解耦的作用在于如果后面要我改成从阿里云oss上传文件&#xff0c;我只需要实现上传逻辑从七牛改成阿里云即可&#xff0c;其他不用动。实现方式有2部分组成&#xff0c;一部分是上传逻辑&#xff0c;一部分是ui。 上传逻辑 大概逻辑就是先去服务端拿上传token和地址&#xff0…

酒水类目电商代运营公司-品融电商:全域策略驱动品牌长效增长

酒水类目电商代运营公司-品融电商&#xff1a;全域策略驱动品牌长效增长 在竞争日益激烈的酒水市场中&#xff0c;品牌如何快速突围并实现长效增长&#xff1f;品融电商凭借「效品合一 全域增长」方法论与全链路运营能力&#xff0c;成为酒水类目代运营的领跑者。从品牌定位、视…

机器学习特征工程中的数值分箱技术:原理、方法与实例解析

标题&#xff1a;机器学习特征工程中的数值分箱技术&#xff1a;原理、方法与实例解析 摘要&#xff1a; 分箱技术作为机器学习特征工程中的关键环节&#xff0c;通过将数值数据划分为离散区间&#xff0c;能够有效提升模型对非线性关系的捕捉能力&#xff0c;同时增强模型对异…

【MySQL专栏】MySQL数据库的复合查询语句

文章目录 1、首先练习MySQL基本语句的练习①查询工资高于500或岗位为MANAGER的雇员&#xff0c;同时还要满足他们的姓名首字母为大写的J②按照部门号升序而雇员的工资降序排序③使用年薪进行降序排序④显示工资最高的员工的名字和工作岗位⑤显示工资高于平均工资的员工信息⑥显…

Python爬虫(5)静态页面抓取实战:requests库请求头配置与反反爬策略详解

目录 一、背景与需求‌二、静态页面抓取的核心流程‌三、requests库基础与请求头配置‌3.1 安装与基本请求3.2 请求头核心参数解析‌3.3 自定义请求头实战 四、实战案例&#xff1a;抓取豆瓣读书Top250‌1. 目标‌2. 代码实现3. 技术要点‌ 五、高阶技巧与反反爬策略‌5.1 动态…

HTML给图片居中

在不同的布局场景下&#xff0c;让 <img> 元素居中的方法有所不同。下面为你介绍几种常见的居中方式 1. 块级元素下的水平居中 如果 <img> 元素是块级元素&#xff08;可以通过 display: block 设置&#xff09;&#xff0c;可以使用 margin: 0 auto 来实现水平居…

【高频考点精讲】前端构建工具对比:Webpack、Vite、Rollup和Parcel

前端构建工具大乱斗:Webpack、Vite、Rollup和Parcel谁是你的菜? 【初级】前端开发工程师面试100题(一) 【初级】前端开发工程师面试100题(二) 【初级】前端开发工程师的面试100题(速记版) 最近在后台收到不少同学提问:“老李啊,现在前端构建工具这么多,我该选哪个?…

赶紧收藏!教您如何用 GitHub 账号,获取永久免费的 Docker 容器!!快速搭建我们的网站/应用!

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 永久免费的 Docker 容器 📒🚀 注册与登录➕ 创建 Docker 容器💻 部署你的网站🔑 注意事项💡 使用场景⚓️ 相关链接 ⚓️📖 介绍 📖 还在为搭建个人网站寻找免费方案而烦恼? 今天发现一个宝藏平台!只需一个 Git…

Java大师成长计划之第3天:Java中的异常处理机制

&#x1f4e2; 友情提示&#xff1a; 本文由银河易创AI&#xff08;https://ai.eaigx.com&#xff09;平台gpt-4o-mini模型辅助创作完成&#xff0c;旨在提供灵感参考与技术分享&#xff0c;文中关键数据、代码与结论建议通过官方渠道验证。 在 Java 编程中&#xff0c;异常处理…

大数据去重

实验4 大数据去重 1.实验目的 通过Hadoop数据去重实验&#xff0c;学生可以掌握准备数据、伪分布式文件系统配置方法&#xff0c;以及在集成开发环境Eclipse中实现Hadoop数据去重方法。 2.实验要求 了解基于Hadoop处理平台的大数据去重过程&#xff0c;理解其主要功能&…