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.pswp.cn/bicheng/78306.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/78306.shtml
英文地址,請注明出處:http://en.pswp.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;理解其主要功能&…