Springboot纯后端将ECharts统计图转为图片

Springboot纯后端将ECharts统计图转为图片

简介:项目中要求是不经过前端,纯后端将ECharts统计图生成图片并转成base64码,以接口的形式提供调用,统计图所需参数接口预留。
此文章有三处工具记录
1.将jar包通过项目引入maven,无需将jar包打入maven库;
2.将ECharts图表生成图片保存至本地文件夹;
3.本地图片转为base64码。

直奔主题,程序所需文件已放至网盘
链接:https://pan.baidu.com/s/1R1A6LJndtojBleTG_qXngw
提取码:z5u2 在这里插入图片描述
1.将程序所需jar包放入项目里,使用Pom引入的方法
在项目里新建一个lib包,将jar包放进去,然后pom指定路径,更新maven

<!--本地包引入-->
<dependency>
	<groupId>ECharts-2.2.7</groupId>
	<artifactId>ECharts</artifactId>
	<version>2.2.7</version>
	<scope>system</scope>
	<systemPath>${project.basedir}/src/main/resources/lib/ECharts-2.2.7.jar</systemPath>
</dependency>

2.将phantomjs配置为环境变量
在这里插入图片描述
3.在本地新建两个文件夹,程序要用到,一个存储ECharts生成的json文件,一个存储图片
在这里插入图片描述
4.代码块
图片生成方法,注意封装的所需参数去调用
optiona里为原生ECharts,可在ECharts官网实例选择所需要的图表,将其代码放入optiona变量里
所需参数示例在下文接口封装调用处

import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class EChartLines {

    private static final String JSpath = "D:\\temp\\phantomjs-2.1.1-windows64\\echarts-convert\\echarts-convert1.js";

    public static String eChartsImage(String xData,String thisCount,String lastCount,String title,String thisName,String lastName) {
        String imgName = "D:/temp/Echart/tes" + UUID.randomUUID().toString().substring(0, 4) + ".png ";
        String optiona ="{title: {\r\n" +
                "        text:"+"'"+title+"'}," +
                "    tooltip: {\r\n" +
                "        trigger: 'axis'\r\n" +
                "    },\r\n" +
                "    legend: {\r\n" +
                "        data:"+"['"+thisName+"','"+lastName+"']" +
                "    },\r\n" +
                "    grid: {\r\n" +
                "        left: '3%',\r\n" +
                "        right: '4%',\r\n" +
                "        bottom: '3%',\r\n" +
                "        containLabel: true\r\n" +
                "    },\r\n" +
                "    xAxis: {\r\n" +
                "axisLabel:{interval:0,rotate:45},"+
                "        type: 'category',\r\n" +
                "        boundaryGap: false,data: " +
                xData+
                "    },\r\n" +
                "    yAxis: {\r\n" +
                "        type: 'value'\r\n" +
                "    },\r\n" +
                "    series: [\r\n" +
                "        {\r\n" +
                "            name:"+"'"+thisName+"'," +
                "            type: 'line',\r\n" +
                "            stack: '总量',data: " +
                thisCount +","+
                "            stack:\"stack\",label: {normal:{show:true,position:'top'}}" +
                "        },\r\n" +
                "        {\r\n" +
                "            name:"+"'"+lastName+"'," +
                "            type: 'line',\r\n" +
                "            stack: '总量',label: {normal:{show:true,position:'button'}},data: " +
                lastCount +
                "        }\r\n" +
                "    ]}";
        Map<String,Object> resultMap=new HashMap<>();
        String imagePathName = generateEChart(optiona, resultMap);
        return imagePathName;
    }

    public static String generateEChart(String options, Map<String,Object> resultMap) {
        String dataPath = writeFile(options);
        String fileName= UUID.randomUUID().toString().substring(0, 8) + ".png";
        String path = "D:/temp/Echart/" +fileName;
        try {
            File file = new File(path);     //文件路径(路径+文件名)
            if (!file.exists()) {   //文件不存在则创建文件,先创建目录
                File dir = new File(file.getParent());
                dir.mkdirs();
                file.createNewFile();
            }
            String cmd = "phantomjs " + JSpath + " -infile " + dataPath + " -outfile " + path;
            System.out.println(cmd);
            Process process = Runtime.getRuntime().exec(cmd);
            BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line = "";
            while ((line = input.readLine()) != null) {
            }
            input.close();

        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            return path;
        }
    }

    public static String writeFile(String options) {
        String dataPath="D:\\chartData\\data"+ UUID.randomUUID().toString().substring(0, 8) +".json";
        try {
            /* 写入Txt文件 */
            File writename = new File(dataPath); // 相对路径,如果没有则要建立一个新的output.txt文件
            if (!writename.exists()) {   //文件不存在则创建文件,先创建目录
                File dir = new File(writename.getParent());
                dir.mkdirs();
                writename.createNewFile(); // 创建新文件
            }
            BufferedWriter out = new BufferedWriter(new FileWriter(writename));
            out.write(options);
            out.flush(); // 把缓存区内容压入文件
            out.close(); // 最后记得关闭文件
        } catch (IOException e) {
            e.printStackTrace();
        }
        return dataPath;
    }
}

参数实体类

import lombok.Data;

/**
 * 双折线,柱状图共用参数类
 */
@Data
public class EChartsDoubleParamVo {

    private String title; // 图标题

    private String thisName; // 本期图例及统计柱线名称(必填)

    private String lastName; // 上期图例及统计柱线名称(必填)

    private String name; // ['0点~1点'] 参数样例 x轴

    private String thisCount; // 当期

    private String lastCount; // 上期
}

base64转换工具类

import sun.misc.BASE64Encoder;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Objects;

public class ImageToBase64Util {
    private static String strNetImageToBase64;

    /**
     * 网络图片转换Base64的方法
     *
     * @param netImagePath
     */
    private static void NetImageToBase64(String netImagePath) {
        final ByteArrayOutputStream data = new ByteArrayOutputStream();
        try {
            // 创建URL
            URL url = new URL(netImagePath);
            final byte[] by = new byte[1024];
            // 创建链接
            final HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(5000);

            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        InputStream is = conn.getInputStream();
                        // 将内容读取内存中
                        int len = -1;
                        while ((len = is.read(by)) != -1) {
                            data.write(by, 0, len);
                        }
                        // 对字节数组Base64编码
                        BASE64Encoder encoder = new BASE64Encoder();
                        strNetImageToBase64 = encoder.encode(data.toByteArray());
                        System.out.println("网络图片转换Base64:" + strNetImageToBase64);
                        // 关闭流
                        is.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }).start();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 本地图片转换Base64的方法
     *
     * @param imgPath
     */
    public static String ImageToBase64(String imgPath) {
        byte[] data = null;
        // 读取图片字节数组
        try {
            InputStream in = new FileInputStream(imgPath);
            data = new byte[in.available()];
            in.read(data);
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 对字节数组Base64编码
        BASE64Encoder encoder = new BASE64Encoder();
        // 返回Base64编码过的字节数组字符串
        String base64Image = "data:image/png;base64,"+encoder.encode(Objects.requireNonNull(data));
        return base64Image;
    }
}

接口调用类

/**
 * ECharts图表转图片
 */
@RestController
@RequestMapping("/eCharts")
public class EChartsImageController {

    /**
     * 双折线图表
     * @param eChartsDoubleParamVo
     * @return
     */
    @PostMapping("/eChartLinesBase64")
    public ActionResult EChartLinesBase64(@RequestBody EChartsDoubleParamVo eChartsDoubleParamVo){
        ActionResult actionResult = null;
        try {
            String title = eChartsDoubleParamVo.getTitle();
            String xData = eChartsDoubleParamVo.getName();
            String thisCount = eChartsDoubleParamVo.getThisCount();
            String lastCount = eChartsDoubleParamVo.getLastCount();
            String thisName = eChartsDoubleParamVo.getThisName();
            String lastName = eChartsDoubleParamVo.getLastName();

            String imagePath = EChartLines.eChartsImage(xData,thisCount,lastCount,title,thisName,lastName); // 图片路径
            String base64Image = ImageToBase64Util.ImageToBase64(imagePath);
            base64Image = base64Image.replaceAll("\r|\n", "");
            return actionResult = new ActionResult(200,"获取成功",base64Image);
        } catch (Exception e){
            e.printStackTrace();
            actionResult = new ActionResult(500,"操作失败",null);
        }
        return actionResult;
    }
}

Controller接口返回规范类

import lombok.AllArgsConstructor;
import lombok.Data;
import java.io.Serializable;

/**
 * rest返回数对象
 */
@Data
@AllArgsConstructor
public class ActionResult<T> implements Serializable {
    private static final long serialVersionUID = 6116515098874945764L;
    private int code;
    private String message;
    private T content;

    public ActionResult() {
    }
}

接口调用参数示例

{
    "title":"警情时段图",
    "name":"['0点~1点', '1点~2点', '2点~3点', '3点~4点', '4点~5点', '5点~6点', '6点~7点','7点~8点','8点~9点','9点~10点','10点~11点','11点~12点']",
    "thisCount":"[156, 111, 73, 71, 53, 89, 206, 533, 570, 559, 506, 448]",
    "lastCount":"[161, 105, 80, 49, 54, 90, 205, 503, 536, 486, 464, 401]",
    "thisName":"今年同期数量",
    "lastName":"去年同期数量"
}

因为是Springboot项目,在打成jar包发布的时候,调用接口生成ECharts图表会有中文乱码情况,故采用utf-8编码启动

java -jar -Dfile.encoding=utf-8 web.jar

文章至此结束,一个开发笔记,也希望能帮助到有类似需求的朋友!

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值