Java服务端使用freemarker+wkhtmltoimage生成Echart图片
目录
1.通过 freemarker 将ftl转成html
1.1 freemarker 手册:
1.2 添加freemarker maven依赖
1.3 添加 echart-test.ftl 模版文件
1.4 添加 FreemarkerTool 工具类
1.5 添加测试main方法
1.6 运行,生成echart-test-时间戳.html 文件
2. 通过wkhtmltoimage将html 转为png图片
2.1 下载 wkhtmltoimage
2.2 下载后安装(略)
2.3 添加 WkhtmltopdfTool 工具类
2.4 添加 HtmlToPdfThread 工具类
2.5 添加main方法测试
2.6 运行,生成 echart-test-时间戳.png 图片
2.7 注意
1.通过 freemarker 将ftl转成html
1.1 freemarker 手册:
FreeMarker 中文官方参考手册
Echart官网 Examples - Apache ECharts
1.2 添加freemarker maven依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId><version>2.5.1</version>
</dependency>
1.3 添加 echart-test.ftl 模版文件
文件内容:
<html><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><title>ECharts Demo</title><script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/5.2.2/echarts.min.js"integrity="sha512-ivdGNkeO+FTZH5ZoVC4gS4ovGSiWc+6v60/hvHkccaMN2BXchfKdvEZtviy5L4xSpF8NPsfS0EVNSGf+EsUdxA=="crossorigin="anonymous" referrerpolicy="no-referrer"></script><style>body {margin: 0;display: flex;flex-direction: row;justify-content: center;}#display-container {width: 600px;height: 600px;border: 2px solid black;}</style>
</head><body>
<div id="container"><div id="display-container"></div>
</div><script type="text/javascript">var chart = echarts.init(document.getElementById("display-container"));var option = {"animation": false,"xAxis": {"type": "category","axisTick": {"alignWithLabel": true},"data": ${xAxisData!'[]'}},"yAxis": {"type": "value"},"tooltip": {"axisPointer": {"type": "shadow"},"trigger": "axis"},"series": [{"type": "bar","name": "Direct","data": ${yAxisData!'[]'},"barWidth": "60%"}]}chart.setOption(option);
</script>
</body></html>
1.4 添加 FreemarkerTool 工具类
package com.hanyc.demo.util;import cn.hutool.core.collection.ListUtil;
import com.alibaba.fastjson.JSON;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import lombok.extern.slf4j.Slf4j;import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** @author :hanyc* @date :2024/1/25 11:15* @description:*/
@Slf4j
public class FreemarkerTool {/*** 根据模板,利用提供的数据,生成文件** @param sourceFile 模板文件名* @param data 模版数据* @param destFile 最终生成的文件,需要携带路径*/public static void data2html(String sourceFile, Map<String, Object> data, String destFile) throws IOException, TemplateException {// 如果文件夹不存在 则创建FileUtil.createFile(new File(destFile));Writer out = null;try {out = new FileWriter(new File(destFile));Configuration cfg = new Configuration(Configuration.VERSION_2_3_29);// 文件所在位置目录cfg.setDirectoryForTemplateLoading(new File("D:/code/springbootdemo2/src/main/resources/template/"));Template template = cfg.getTemplate(sourceFile);template.process(data, out);} catch (Exception e) {log.error("模板生成报告html文件异常", e);throw e;} finally {try {if (out != null) {out.flush();out.close();}} catch (IOException e) {e.printStackTrace();}}}
}
1.5 添加测试main方法
public static void main(String[] args) throws IOException, InterruptedException, TemplateException {// 文件名String sourceFile = "echart-test.ftl";// 渲染存储数据Map<String, Object> datas = new HashMap<String, Object>();List<String> xAxisData = ListUtil.of("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun");datas.put("xAxisData", JSON.toJSONString(xAxisData));List<Integer> yAxisData = ListUtil.of(10, 52, 200, 334, 390, 330, 220);datas.put("yAxisData", JSON.toJSONString(yAxisData));//最终生成的文件路径String destFile = "D:\\code\\springbootdemo2\\src\\main\\resources\\template\\echart-test-" + System.currentTimeMillis() + ".html";data2html(sourceFile, datas, destFile);}
1.6 运行,生成echart-test-时间戳.html 文件
2. 通过wkhtmltoimage将html 转为png图片
2.1 下载 wkhtmltoimage
- 官网地址:wkhtmltopdf
https://wkhtmltopdf.org/ - 官网下载地址:wkhtmltopdf
https://wkhtmltopdf.org/downloads.html
2.2 下载后安装(略)
2.3 添加 WkhtmltopdfTool 工具类
package com.hanyc.demo.util;import cn.hutool.core.collection.ListUtil;
import com.alibaba.fastjson.JSON;
import freemarker.template.TemplateException;
import lombok.extern.slf4j.Slf4j;import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** @author :hanyc* @date :2024/1/25 9:33* @description: wkhtmltopdf 工具类*/
@Slf4j
public class WkhtmltopdfTool {private static final String WKHTMLTOPDF_PATH = "D:\\ruanjian\\wkhtmltopdf\\bin\\wkhtmltoimage.exe"; // 替换为实际路径/*** html转pdf** @param srcPath html路径,可以是硬盘上的路径,也可以是网络路径* @param destPath 图片保存路径* @param width 宽度*/public static void convert(String srcPath, String destPath, Integer width) throws IOException, InterruptedException {File file = new File(destPath);File parent = file.getParentFile();//如果pdf保存路径不存在,则创建路径if (!parent.exists()) {parent.mkdirs();}StringBuilder cmd = new StringBuilder();cmd.append(WKHTMLTOPDF_PATH);cmd.append(" ");// 去掉左右 边距
// cmd.append(" --margin-left 0mm --margin-right 0mm --margin-top 0mm --margin-bottom 5mm ");
// cmd.append(" --enable-local-file-access ");//设置页面上边距 (default 10mm)
// cmd.append(" --margin-top 0mm ");//设置页面下边距 (default 10mm)
// cmd.append(" --margin-bottom 0mm ");// (设置页眉和内容的距离,默认0)
// cmd.append(" --header-spacing 0 ");// 添加页码
// cmd.append(" --footer-center [page]/[topage] ");// 1.--format.\<格式》:指定输出图像的格式。可以是PNG、JPEG、BMP等,默认为PNG。cmd.append(" --format png ");// 2 . –quality 75:就表示生成图片的质量为原来的 75%!cmd.append(" --quality 75 ");
// 3 --width \<宽度\>:设置输出图像的宽度。可以使用像素(如800px)或其他单位(如cm、mm等)指定,默认为 1024像素。if (width != null) {cmd.append(" --width ");cmd.append(width);cmd.append(" ");}
// 4 --height \<高度\>:设置输出图像的高度。同样可以使用像素或其他单位指定,默认为0,表示自适应高度。
// cmd.append(" --height 600");
// 5 --crop-w \<宽度\>:将输入HI文档裁剪为指定宽度的图像。宽度单位与--width相同,默认为0,表示不进行裁剪。
// 6 --crop-h \高度\>:将输入HI文档裁剪为指定高度的图像。高度单位与--height相同,默认为0,表示不进行裁剪。
// 7 --crop-x\<x坐标\>:设置裁剪的左上角x坐标。默认为0。
// 8 --crop-y \<y坐标\>:设置裁剪的左上角y坐标。默认为0。
// 9. --no-outline:禁用轮廓线,即去掉输出图像中的边框线
// 10 .--no-background:禁用背景,即去掉输出图像中的背景色。
// 11 --disable-smart-width:禁用智能调整宽度,即不根据内容自适应调整宽度。
// 12 --transparent:将输出图像的背景色设置为透明。
// 13.--encoding<编码》>:设置HTML文档的字符编码
// 14.--quiet:静默模式,不输出任何日志信息。
// 15 --version:显示wkhtmltoimage的版本信息cmd.append(srcPath);cmd.append(" ");cmd.append(destPath);boolean result = true;try {log.info("执行命令: {}", cmd.toString());Process proc = Runtime.getRuntime().exec(cmd.toString());HtmlToPdfThread error = new HtmlToPdfThread(proc.getErrorStream());HtmlToPdfThread output = new HtmlToPdfThread(proc.getInputStream());error.start();output.start();proc.waitFor();} catch (Exception e) {result = false;log.error("html转pdf fail:{}", e.getMessage(), e);throw e;}}}
}
2.4 添加 HtmlToPdfThread 工具类
package com.hanyc.demo.util;import cn.hutool.core.io.IoUtil;
import lombok.extern.slf4j.Slf4j;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;/*** @author :hanyc* @date :2023/4/26 14:44* @description: 流处理日志输出工具类*/
@Slf4j
public class HtmlToPdfThread extends Thread {private InputStream is;public HtmlToPdfThread(InputStream is) {this.is = is;}@Overridepublic void run() {BufferedReader br = null;try {InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8);br = new BufferedReader(isr);String line = null;while ((line = br.readLine()) != null) {//输出内容log.info(line);}} catch (IOException e) {e.printStackTrace();log.error("HtmlToPdfThread: ", e);} finally {IoUtil.close(is);IoUtil.close(br);}}
}
2.5 添加main方法测试
public static void main(String[] args) throws IOException, InterruptedException, TemplateException {String sourceFile = "D:\\code\\springbootdemo2\\src\\main\\resources\\template\\echart-test-1706154543908.html";String destFile = "D:\\code\\springbootdemo2\\src\\main\\resources\\template\\echart-test-1706154543908.png";WkhtmltopdfTool.convert(sourceFile, destFile,550);}
2.6 运行,生成 echart-test-时间戳.png 图片

2.7 注意
wkhtmltopdf / wkhtmltoimage 官网已经不再维护,如果生成的图片和原html不一样,或转化错误,可以尝试将js或css代码改为较原始的版本.
相关文章:
Java服务端使用freemarker+wkhtmltoimage生成Echart图片
目录 1.通过 freemarker 将ftl转成html 1.1 freemarker 手册: 1.2 添加freemarker maven依赖 1.3 添加 echart-test.ftl 模版文件 1.4 添加 FreemarkerTool 工具类 1.5 添加测试main方法 1.6 运行,生成echart-test-时间戳.html 文件 2. 通过wkhtmltoimage将html 转为p…...
一款颜值与实力并存的翻页时钟(免费)
FliTik是一款颜值与实力并存的翻页时钟,安卓端是完全免费的,无任何广告,极简风 ,软件默认是12小时制,可以在设置中启用24小时制,并且还支持设置显示秒钟、日期、文案,滴答声和语音报时。 支持横…...
Objective-C方法的声明实现及调用
1.无参数的方法 1)声明 a.位置:在interface括弧的外面 b.语法: - (返回值类型)方法名称; interface Person : NSObject -(void) run; end 2)实现 a.位置:在implementation中实现 b.语法:加大括弧将方法实现的代码写在大括孤之中 …...
第十四届蓝桥杯国赛 C++ B 组 C 题——班级活动(AC)
目录 1. 班级活动1. 问题描述2. 输入格式3. 输出格式4. 样例输入5. 样例输出6. 样例说明7. 评测用例规模与约定8. 原题链接 2. 解题思路3. AC_Code 1. 班级活动 前置知识点:思维,分类讨论 1. 问题描述 小明的老师准备组织一次班级活动。班上一共有 n…...
GraphQL的力量:简化复杂数据查询
1. GraphQL GraphQL 是一种由 Facebook 开发并于 2015 年公开发布的数据查询和操作语言,也是运行在服务端的运行时(runtime)用于处理 API 查询的一种规范。不同于传统的 REST API,GraphQL 允许客户端明确指定它们需要哪些数据&am…...
python环境安装sklearn及报错解决
安装 如刚开始安装,还未遇到问题请直接从重新安装库开始看,如果遇到报错,从问题开始看 问题 python安装sklearn报错 ,报错信息如下 File "<stdin>", line 1pip install scikit-learn^ SyntaxError: invalid s…...
log4j:WARN Please initialize the log4j system properly的解决办法
背景:很多次创建新项目log4j都出现以下2个警告: log4j:WARN No appenders could be found for logger (org.springframework.boot.ApplicationServletEnvironment).log4j:WARN Please initialize the log4j system properly 网上查询都是在说缺少以下jar…...
虹科分享丨汽车技术的未来:Netropy如何测试和确保汽车以太网的性能
来源:艾特保IT 虹科分享丨汽车技术的未来:Netropy如何测试和确保汽车以太网的性能 原文链接:https://mp.weixin.qq.com/s/G8wihrzqpJJOx5i0o63fkA 欢迎关注虹科,为您提供最新资讯! #汽车以太网 #车载网络 #Netropy …...
代码CE:reference to ‘XX‘ is ambiguous
代码CE:reference to ‘XX’ is ambiguous 今天提交代码的时候一直错误,CE,搞不明白明明在dev上成功,为什么提交失败。 现在懂了,因为定义的变量和C内部函数或变量重名了。修改之后即可AC。 int data[21][21]{0}; int maxsum[21…...
如果想将企业微信的组织架构同步到内部知识库咋搞?方法来也!
在现代企业的运营中,内部知识库不仅储存了公司的宝贵知识资产,还充当着员工信息共享和协作的核心平台。为了保障知识库的效能最大化,使其成为支持决策、创新和培训的强大工具,企业必须拥有一套周到的权限管理机制。对此࿰…...
【c语言】扫雷
前言: 扫雷是一款经典的单人益智游戏,它的目标是在一个方格矩阵中找出所有的地雷,而不触碰到任何一颗地雷。在计算机编程领域,扫雷也是一个非常受欢迎的项目,因为它涉及到许多重要的编程概念,如数组、循环…...
自然语言处理的崛起:从初步分析到深度理解
自然语言处理(NLP)是计算机科学、人工智能和语言学的交叉领域,旨在让计算机能够理解和生成人类语言。随着时间的推移,NLP 经历了一系列革命性的变化,从简单的规则和模式匹配到如今的深度学习模型,它们使计算…...
Git学习笔记:版本回滚
文章目录 回到过去:开启新时间线,时间分叉路口1. 回溯开发2. 临时恢复特性3. 实验性开发4. 分支维护和发布5. 调试历史问题类比推理: 方法:1. 临时查看旧版本2. 永久回滚到旧版本3. 创建新的分支指向旧版本 回到过去:开…...
OpenCV图像的基本操作
图像的基本操作(Python) 素材图 P1:die.jpg P2:cool.jpg V:rabbit.mp4, 下载地址 读取展示-图像 import cv2img_1 cv2.imread(./die.jpg) # default cv2.IMREAD_COLOR print("die.jpg shape(imre…...
小白水平理解面试经典题目LeetCode 594 Longest Harmonious Subsequence(最大和谐字符串)
594 最大和谐字符串 这道题属于字符串类型题目,解决的办法还是有很多的,暴力算法,二分法,双指针等等。 题目描述 和谐数组是指一个数组里元素的最大值和最小值之间的差别 正好是 1 。 现在,给你一个整数数组 nums …...
Vue-35、Vue中使用ref属性
1、ref属性 2、代码 <template><div id"app"> <!-- <img alt"Vue logo" src"./assets/logo.png">--><h1 v-text"msg" ref"title"></h1><button click"showDOM" ref&…...
网络通信(15)-C#TCP客户端掉线重连实例
本文上接前面的文章使用Socket在C#语言环境下完成TCP客户端的掉线重连实例。 掉线重连需要使用心跳包发送测试网络的状态,进而进入重连循环线程。 前面实例完成的功能: 客户端与服务器连接,实现实时刷新状态。 客户端接收服务器的数据。 客户端发送给服务器的数据。 客…...
React进阶 - 14(说一说”虚拟DOM“中的”Diff算法“)
本章内容 目录 一、了解 Diff 算法二、key 值的重要性三、为什么不建议使用 index 做 key 值 上一节我们初步了解了 React中的”虚拟 DOM“ ,本节我们来说一说”虚拟DOM“中的”Diff算法“ 一、了解 Diff 算法 在上一篇中,我们有讲到:当 st…...
#GPU|LLM|AIGC#集成显卡与独立显卡|显卡在深度学习中的选择与LLM GPU推荐
区别 核心区别:显存,也被称作帧缓存。独立显卡拥有独立显存,而集成显卡通常是没有的,需要占用部分主内存来达到缓存的目的 集成显卡: 是集成在主板上的,与主处理器共享系统内存。 一般会在很多轻便薄型的…...
HCIP-IPV6实验
实验拓扑 实验需求 全网可达 实验思路 配置IP地址 配置路由协议-ospf 配置R2 配置IPV6 配置R2Tunnel 将所有地址引流到Tunnel0/0/0接口 ripng配置 汇总 实验步骤 配置IP地址 以R2为例 [Huawei]sys r2 [r2]int g0/0/0 [r2-GigabitEthernet0/0/0]ip address 12.1.1…...
Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...
使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...
基于Java+MySQL实现(GUI)客户管理系统
客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息,对客户进行统一管理,可以把所有客户信息录入系统,进行维护和统计功能。可通过文件的方式保存相关录入数据,对…...
MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...
tomcat入门
1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效,稳定,易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...
OD 算法题 B卷【正整数到Excel编号之间的转换】
文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的:a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...
