springboot之HTML與圖片生成

背景

后臺需要根據字段動態生成HTML,并生成圖片,發送郵件到給定郵箱

依賴

 <!-- freemarker模板引擎-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId><version>2.7.17</version>
</dependency>
<!-- 圖片生成 -->
<dependency><groupId>org.xhtmlrenderer</groupId><artifactId>core-renderer</artifactId><version>R8</version>
</dependency>

HTML模版 (ftl格式模板)

<!-- demo.ftl -->
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8" /><title>demo Receipt</title><style>body {font-family: Arial, sans-serif;background-color: #f0f0f0;margin: 20px;}hr {border: none;border-bottom:1px dashed black;}.receipt {background-color: #fff;padding: 20px;border-radius: 8px;box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);width: 320px;text-align: center;margin: 0 auto;}.fieldLabel, .fieldMiddle, .fieldValue {margin: 0 auto; /* 使子元素水平居中 */}.fieldLabel {font-size: 14px;/*font-weight: bold;*/text-align: left;}.fieldMiddle {font-size: 14px;/*font-weight: bold;*/text-align: left;}.fieldValue {font-size: 14px;text-align: right;}</style>
</head>
<body>
<!-- <div style="text-align: center; padding: 20px"> -->
<div class="receipt"><table>
<#--        content1--><#if content1??><tr><!-- 水平實線 --><td colspan="10"><hr/></td></tr><#list content1 as item><tr><td colspan="4" class="fieldLabel">${item.fieldName}</td><td colspan="1" class="fieldMiddle">:</td><td colspan="5" class="fieldValue">${item.fieldValue}</td></tr></#list></#if>
<#--        content2--><#if content2??><tr><!-- 水平實線 --><td colspan="10"><hr/></td></tr><#list content2 as item><tr><td colspan="4" class="fieldLabel">${item.fieldName}</td><td colspan="1" class="fieldMiddle">:</td><td colspan="5" class="fieldValue">${item.fieldValue}</td></tr></#list></#if></table>
</div>
</body>
</html>

ftl相關類

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ReceiptFieldDto {private String fieldName;private String fieldValue;
}

函數

/*** 獲取ftl模板轉為html*/
public static String ftlToString(Map<String, Object> map, String templateName) throws IOException,TemplateException {String value = "";Configuration configuration = new Configuration(Configuration.VERSION_2_3_32);// 模板路徑String ftlPath = System.getProperty("user.dir") + File.separator + "templates";String encoding = "UTF-8";configuration.setDefaultEncoding(encoding);StringWriter out = new StringWriter();configuration.setDirectoryForTemplateLoading(new File(ftlPath));Template template = configuration.getTemplate(templateName, Locale.US, encoding);template.process(map, out);out.flush();out.close();value = out.getBuffer().toString();return value;
}/**
* html: html內容
* inputFileName: 輸入文件名絕對路徑
* outputFileName: 輸出文件名絕對路徑
* widthImage:圖片寬
* heightImage:圖片高
*/
public static String turnImage(String html, String inputFileName, String outputFileName, int widthImage, int heightImage) throws IOException {File inputFile = new File(inputFileName);File inputDir = inputFile.getParentFile();if (!inputFile.exists()) {if (inputDir != null) {inputDir.mkdirs();}inputFile.createNewFile();}try (BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(inputFile), StandardCharsets.UTF_8))) {String specialHtml = html.replace("&", "&amp;");bufferedWriter.write(specialHtml);bufferedWriter.newLine();}File outputFile = new File(outputFileName);File outputDir = outputFile.getParentFile();if (!outputFile.exists()) {if (outputDir != null) {outputDir.mkdirs();}outputFile.createNewFile();}Java2DRenderer renderer = new Java2DRenderer(inputFile, widthImage, heightImage);BufferedImage image = renderer.getImage();FSImageWriter imageWriter = new FSImageWriter();imageWriter.setWriteCompressionQuality(0.9f);try (FileOutputStream fout = new FileOutputStream(outputFile)) {imageWriter.write(image, fout);}return outputFileName;
}public static void deleteTempFolder(String folderPath) {FileUtils.deleteQuietly(new File(folderPath));
}private void initMap(Map<String, Object> map) {ArrayList<ReceiptFieldDto> content1List = new ArrayList<>();content1List.add(new ReceiptFieldDto("第一行標題", "第一行內容"));map.put("content1", content1List);ArrayList<ReceiptFieldDto> content2List = new ArrayList<>();content2List.add(new ReceiptFieldDto("第二行標題", "第二行內容"));map.put("content2", content2List);
}

測試

public String generateImage(){UUID uuid = UUID.randomUUID();String tempFolder = System.getProperty("user.dir") + File.separator + "tmp" + File.separator + uuid.toString().replace("-", "");try {Map<String, Object> map = new HashMap<>();initMap(map);String html = ftlToString(map, "demo.ftl");String htmlPath = tempFolder + File.separator + "demo.html";String imagePath = tempFolder + File.separator + "demo.jpg";int imageWidth = 400;int imageHeight = 600;try {turnImage(html, htmlPath, imagePath, imageWidth, imageHeight);} catch (IOException e) {e.printStackTrace();}return imagePath;} catch (Exception e) {e.printStackTrace();}finally {deleteTempFolder(tempFolder);}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/72104.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/72104.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/72104.shtml

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

相關文章

《從0到1:用Python在鴻蒙系統開發安防圖像分類AI功能》

在人工智能與移動應用深度融合的當下,類目標簽AI功能成為眾多行業提升效率和用戶體驗的關鍵技術。本文聚焦于HarmonyOS NEXT API 12及以上版本,以圖像分類在智能家居安防領域的應用為例,為開發者詳細闡述如何利用Python開發類目標簽AI功能,助力鴻蒙技術在該領域的創新應用。…

【AD】3-10 原理圖PDF導出

文件—智能PDF 多頁原理圖導出 導出設置時選擇工程&#xff0c;可自行選擇導出一頁或多頁原理圖&#xff0c;一般PCB不用導出

【deepseek第一課】從0到1介紹 采用ollama安裝deepseek私有化部署,并實現頁面可視化

【deepseek第一課】從0到1介紹 采用ollama安裝deepseek私有化部署,并實現頁面可視化 1. ollama安裝1.1 linux安裝1.2 windows安裝2. deepSeek支持的7種蒸餾模型2.1 蒸餾模型介紹2.2 7種模型特點2.3 安裝deepseek-r1:14b模型3. openwebui圖形化頁面安裝4. java連接大模型的三…

【在線用戶監控】在線用戶查詢、強退用戶

文章目錄 在線用戶監控在線用戶監控API(RestController)當前在線會話在線用戶查詢強退用戶知識擴展: JwtJwtTokenUtil生成jwt解析token登錄授權的實現:json web token + redis + springboot在線用戶監控 在線用戶監控API(RestController) @RestController @Tag(name = &qu…

超詳細,多圖文介紹redis集群方式并搭建redis偽集群

超詳細&#xff0c;多圖文介紹redis集群方式并搭建redis偽集群 超多圖文&#xff0c;對新手友好度極好。敲命令的過程中&#xff0c;難免會敲錯&#xff0c;但為了截好一張合適的圖&#xff0c;一旦出現一點問題&#xff0c;為了好的演示效果&#xff0c;就要從頭開始敲。且看且…

Hue Load Balance配置

個人博客地址&#xff1a;Hue Load Balance配置 | 一張假鈔的真實世界 直接上配置&#xff1a; server {server_name 192.168.72.31;listen 8001;charset utf-8;proxy_connect_timeout 600s;proxy_read_timeout 600s;proxy_send_timeout 600s;location / {proxy_set_header H…

992. K 個不同整數的子數組

目錄 一、題目二、思路2.1 解題思路2.2 代碼嘗試2.3 疑難問題 三、解法四、收獲4.1 心得4.2 舉一反三 一、題目 二、思路 2.1 解題思路 2.2 代碼嘗試 class Solution { public:int subarraysWithKDistinct(vector<int>& nums, int k) {//需要有數據結構來存儲數組…

領域驅動設計:事件溯源架構簡介

概述 事件溯源架構通常由3種應用設計模式組成,分別是:事件驅動(Event Driven),事件溯源(Event Source)、CQRS(讀寫分離)。這三種應用設計模式常見于領域驅動設計(DDD)中,但它們本身是一種應用設計的思想,不僅僅局限于DDD,每一種模式都可以單獨拿出來使用。 E…

PT2035 TWS 藍牙耳機雙觸控雙輸出 IC

1. 產品概述 PT2035 是一款支持入耳檢測的藍牙耳機專用觸摸芯片&#xff0c;該芯片具有寬工作電壓、低功耗、高抗 干擾能力的特性。 2. 主要特性 工作電壓范圍&#xff1a; 2.4~5.5V 待機電流約 2.5uAV DD3V/CMOD5nF 入耳有效&#xff0c;無觸摸時工作電流約 8uAV DD3…

AI編程界的集大成者——通義靈碼AI程序員

一、引言 隨著軟件行業的快速發展和技術的進步&#xff0c;人工智能&#xff08;AI&#xff09;正在成為軟件開發領域的一個重要組成部分。近年來&#xff0c;越來越多的AI輔助工具被引入到開發流程中&#xff0c;旨在提高效率、減少錯誤并加速創新。在這樣的背景下&#xff0…

Rocky Linux 8.5 6G內存 靜默模式(沒圖形界面)安裝Oracle 19C

Oracle19c 下載地址 Database Software Downloads | Oraclehttps://www.oracle.com/database/technologies/oracle-database-software-downloads.html#db_ee 目錄 一、準備服務器 1、服務器可以克隆、自己裝 2、修改主機名 3、重啟 4、關閉selinux 5、關閉防火墻 5.1、…

另辟蹊徑:多維度解析 STM32 微控制器

開篇&#xff1a;STM32 的廣泛影響力 在嵌入式系統的廣闊天地中&#xff0c;STM32 系列微控制器宛如一顆璀璨的明星&#xff0c;散發著耀眼的光芒。它憑借出色的性能、豐富的資源以及高性價比&#xff0c;在工業、醫療、消費電子等眾多領域廣泛應用&#xff0c;成為無數開發者…

DeepSeek 使用竅門與提示詞寫法指南

一、通用提示詞技巧 竅門分類技巧說明示例提示詞明確需求用“角色任務要求”明確目標作為健身教練&#xff0c;為30歲上班族設計一周減脂計劃&#xff0c;需包含飲食和15分鐘居家訓練結構化提問分步驟、分模塊提問第一步&#xff1a;列出Python爬蟲必備的5個庫&#xff1b;第二…

全監督、半監督、弱監督、無監督

全監督、半監督、弱監督、無監督 全監督學習&#xff08;Fully Supervised Learning&#xff09; 數據標注&#xff1a;使用的數據集包含大量的輸入數據&#xff08;特征&#xff09;以及與之對應的準確標注信息&#xff08;標簽&#xff09;。學習目標&#xff1a;通過學習輸…

c#實現485協議

在C#中實現RS-485協議通信,需要結合串口(SerialPort)操作和硬件收發控制(如RTS信號切換)。以下是詳細的步驟和示例代碼: 1. RS-485通信原理 物理層:RS-485是差分信號標準,支持多點通信(半雙工)。 收發控制:通過控制RTS(Request to Send)或DTR引腳切換發送/接收模式…

刪除變慢問題

問題&#xff1a; 有一個場景&#xff0c;每天都會刪除數據&#xff0c;SQL為delete from xxx where record_date < DATE_SUB(now(), INTERVAL ? DAY) limit 1000 &#xff0c;一直循環執行&#xff0c;當執行到最后一次滿足條件的時候&#xff0c;就會很慢 原理分析 索引與…

lua基礎語法學習

lua基礎語法學習 文章目錄 lua基礎語法學習1. 基礎2. 輸入輸出3. 分支結構與循環結構4. 函數5. 元表與元方法6. 面向對象 1. 基礎 注釋 --單行注釋--[[ 多行注釋 --]]標識符 標識符以一個字母 A 到 Z 或 a 到 z 或下劃線 _ 開頭后加上 0 個或多個字母&#xff0c;下劃線&…

使用DeepSeek實現自動化編程:類的自動生成

目錄 簡述 1. 通過注釋生成C類 1.1 模糊生成 1.2 把控細節&#xff0c;讓結果更精準 1.3 讓DeepSeek自動生成代碼 2. 驗證DeepSeek自動生成的代碼 2.1 安裝SQLite命令行工具 2.2 驗證DeepSeek代碼 3. 測試代碼下載 簡述 在現代軟件開發中&#xff0c;自動化編程工具如…

【SpringBoot】數據訪問技術spring Data、 JDBC、MyBatis、JSR-303校驗

Spring Boot 數據訪問技術及特性 目錄標題 Spring Boot 數據訪問技術及特性摘要1. 引言2. Spring Data架構與原理2.1 Spring Data概述2.2 Spring Data核心組件2.3 Spring Boot與Spring Data的集成機制 3. Spring Boot與JDBC的整合3.1 JDBC整合流程3.2 數據源自動配置3.3 JdbcTe…

【時序預測】深度時序預測算法的對比與核心創新點分析

時間序列預測是機器學習和深度學習領域的重要研究方向&#xff0c;廣泛應用于金融、交通、能源、醫療等領域。近年來&#xff0c;隨著深度學習技術的發展&#xff0c;各種基于深度學習的時間序列預測算法層出不窮。這些算法在模型架構、訓練方式和應用場景上各有特色。本文將對…