Java服务端使用freemarker+wkhtmltoimage生成Echart图片

news2024/11/15 15:15:42

目录

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

  • 官网地址:wkhtmltopdficon-default.png?t=N7T8https://wkhtmltopdf.org/
  • 官网下载地址:wkhtmltopdficon-default.png?t=N7T8https://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;
    }

    @Override
    public 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代码改为较原始的版本.

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

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

相关文章

Flink max maxby区别

max只会显示指定字段的大小变化&#xff0c;而maxBy会显示其他字段的变化。 max&#xff1a;取指定字段的当前的最大值&#xff0c;如果有多个字段&#xff0c;其他非比较字段&#xff0c;以第一条为准。 maxBy&#xff1a;取指定字段的当前的最大值&#xff0c;如果有多个字段…

企业出海数据合规:GDPR下数据出境的条件

一、GDPR对数据出镜的规制 GDPR第五章集中规定了数据跨境流动的形式&#xff0c;总的来说给出了三种个人数据出境的条件&#xff0c;分别是基于充分决定的数据传输&#xff1b;基于采取适当保障措施的数据传输&#xff1b;以及基于特殊情况的减损条款&#xff0c;分别对应的是…

windows下git pull超时,ping不通github

报错 ssh: connect to host github.com port 22: Connection timed out fatal: Could not read from remote repository. Please make sure you have the correct access rights and the repository exists. 解决办法 修改hosts 最后加一行&#xff0c;文件位置&#xff1a;…

Leetcode:二分搜索树层次遍历

题目&#xff1a; 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 示例&#xff1a; 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[[3],[9,…

16、Kafka ------ SpringBoot 整合 Kafka (配置 Kafka 属性 及对应的 属性处理类 解析)

目录 配置 Kafka 及对应的 属性处理类配置KafkaKafka配置属性的约定代码演示生产者相关的配置消费者相关的配置 代码&#xff08;配置文件&#xff09;application.properties 配置 Kafka 及对应的 属性处理类 配置Kafka spring.kafka.* 开头的配置属性&#xff0c;这些属性将由…

MSB20M-ASEMI小功率家电专用MSB20M

编辑&#xff1a;ll MSB20M-ASEMI小功率家电专用MSB20M 型号&#xff1a;MSB20M 品牌&#xff1a;ASEMI 封装&#xff1a;UMSB-4 最大重复峰值反向电压&#xff1a;1000V 最大正向平均整流电流(Vdss)&#xff1a;2A 功率(Pd)&#xff1a;50W 芯片个数&#xff1a;4 引…

OpenHarmony开发——GN快速上手

背景 最近在研究鸿蒙操作系统的开源项目OpenHarmony&#xff0c;该项目使用了GNNinja工具链进行配置&#xff0c;编译&#xff0c;于是开始研究GN如何使用。 本文的所有信息均来自GN官网和本人个人体会。 GN快速入门 使用GN GN的主要功能是根据配置文件&#xff08;.gn, BU…

【排序2】-交换排序

&#x1f47b;交换排序 &#x1f384;1、基本思想及特点&#x1f384;2、冒泡排序&#x1f384;3、快速排序&#xff08;挖坑法&#xff09;&#x1f384;4、快速排序优化&#x1f38a;4.1 三数取中法选key&#x1f38a;4.2 递归到小的子区间时&#xff0c;可以考虑使用插入排序…

Linux零碎点

目录 Linux基础命令 1、who&#xff1a; 2、hostname&#xff1a; 3、ifconfig&#xff1a; 4、pwd&#xff1a; 5、cd&#xff1a; 6、exit&#xff1a; 7、shutdown&#xff1a; 8、ls&#xff1a; 9、创建文件夹&#xff1a; 10、touch&#xff1a; 11、cp&#…

Java PDFBox 提取页数、PDF转图片

PDF 提取 使用Apache 的pdfbox组件对PDF文件解析读取和转图片。 Maven 依赖 导入下面的maven依赖&#xff1a; <dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>2.0.30</version> &l…

实力上榜!安全狗入选《CCSIP 2023中国网络安全行业业全景册(第六版)》多个细项

1月24日&#xff0c;Freebuf发布了《CCSIP 2023中国网络安全行业业全景册&#xff08;第六版&#xff09;》。 作为国内云原生安全领导厂商&#xff0c;安全狗也入选多个细分领域。 厦门服云信息科技有限公司&#xff08;品牌名&#xff1a;安全狗&#xff09;创办于2013年&…

VS2022联合Qt5开发学习10(QT5.12.3联合VTK在VS2022上开发医学图像项目4——ScrollBar控制对比度、切面位置)

这篇博文是接着VS2022联合Qt5开发学习7&#xff08;QT5.12.3联合VTK在VS2022上开发医学图像项目2——十字叉标注&#xff09;-CSDN博客这篇博文延伸开发医学图像的显示渲染相关项目&#xff0c;主要介绍的是在之前显示的图像上增加滑块控制。 用到的内容有&#xff1a; VS2022…

Linux常用命令之文件管理篇

文章目录 前言文件管理命令1、cat 由第一行开始显示文件内容2、ls 列出目录3、cd 切换目录4、mkdir 创建新目录5、touch 创建文件6、 rm 移除文件或目录7、cp 即拷贝文件和目录。8、 mv 移动文件与目录&#xff0c;或修改名称9、 chmod&#xff1a;更改文件9个属性10、chown&am…

Kubernets Deployment详解

因为Pod生命周期是短暂的&#xff0c;一旦运行完成则立即回收&#xff0c;且涉及Pod的创建、自愈、删除等操作比较复杂&#xff0c;所以很少在Kubernetes中直接使用Pod。而是使用更高级的称为Controller&#xff08;控制器&#xff09;的抽象层&#xff0c;来完成对Pod的创建、…

如何解决服务器端口被占用的问题,减少带来的影响

在现代网络环境中&#xff0c;服务器扮演着至关重要的角色&#xff0c;其稳定性和安全性对企业的正常运营具有重要意义。然而&#xff0c;服务器端口被占用的问题却时常困扰着企业网络管理员。本文将深入探讨服务器端口被占用的影响&#xff0c;并提出相应的解决方案。 一、服务…

linux ubuntu下面好用的录屏截图工具kazam 简单好用

kazam可以录屏&#xff0c;可以截图。 安装 apt install kazam使用 开始录制 ctrlmetashiftR 停止&#xff1a; ctrlmetashiftF 保存位置 ~/Videos KKVIEW:一键远控手机电脑

深圳工业元宇宙赋能新型工业化,推动工业制造业数字化转型发展

在当今数字化时代&#xff0c;工业制造业正面临着巨大的变革。随着技术的不断进步&#xff0c;工业元宇宙的概念逐渐成为推动工业制造业数字化转型的重要力量。深圳作为中国的高科技之都&#xff0c;在这方面走在了前列&#xff0c;积极探索工业元宇宙的应用&#xff0c;赋能新…

JUC Future 与 ForkJoin

文章目录 Runable 和 CallableFuture^1.5^FutureTask^1.5^示例 Fork/Join^1.7^ForkJoinPool^1.7^ 线程池任务的类型实例化方式 ForkJoinTask^1.7^示例执行 ForkJoinTask 任务的几个方法 Runable 和 Callable FunctionalInterface public interface Runnable {public abstract …

C语言从入门到入坟

前言 1.初识程序 有穷性 在有限的操作步骤内完成。有穷性是算法的重要特性&#xff0c;任何一个问题的解决不论其采取什么样的算法&#xff0c;其终归是要把问题解决好。如果一种算法的执行时间是无限的&#xff0c;或在期望的时间内没有完成&#xff0c;那么这种算法就是无用…

k8s学习(RKE+k8s+rancher2.x)成长系列之概念介绍(一)

一、前言 本文使用国内大多数中小型企业使用的RKE搭建K8s并拉起高可用Rancher2.x的搭建方式&#xff0c;以相关技术概念为起点&#xff0c;实际环境搭建&#xff0c;程序部署为终点&#xff0c;从0到1的实操演示的学习方式&#xff0c;一步一步&#xff0c;保姆级的方式学习k8…