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.mzph.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;各种基于深度学习的时间序列预测算法层出不穷。这些算法在模型架构、训练方式和应用场景上各有特色。本文将对…