Java通过后台导出Echart图片

Java通过后台导出Echart图片

一,工具准备

phantomjs

由于Echart图片是通过浏览器的js生成在页面上,因此若不想通过前端生成Echart图片,需要使用其他工具,例如 phantomjs,俗称为:*面的浏览器。

PhantomJS是一个基于 WebKit 的服务器端JavaScript API。它全面支持web而不需浏览器支持,支持各种Web标准:DOM处理,CSS选择器, JSON,Canvas,和SVG。
PhantomJS常用于页面自动化,网络监测,网页截屏,以及*面测试等。

通常我们使用PhantomJS作为爬虫工具。传统的爬虫只能单纯地爬取html的代码,对于js渲染的页面,就无法爬取,如Echarts统计图。而PhantomJS正可以解决此类问题。

官网下载http://phantomjs.org/download.html 国内镜像http://npm.taobao.org/dist/phantomjs/

EChartsConvert

echart-convert.js可以配合phantomjs将图片截图下来

下载地址(个人自定义): https://gitee.com/lmchh/echartsconvert

网上地址:https://gitee.com/saintlee/echartsconvert

安装并运行

D:/Java/Echart/phantomjs-2.1.1-windows/bin/phantomjs.exe D:/Java/Echart/echartsconvert/echarts-convert.js -s -p 6666

命令參數:

  • -s: 指通過服務器的方式
  • -p:指定端口後,一般和 -s 一起使用
  • -o:o即option,格式為 {…}
  • -f:輸出路徑
  • -t:圖片類型,有 file/base64 兩種,默認是base64
  • -w:即width,圖片寬度
  • -h:即height,圖片高度

二,所需依赖

		<!--   Echart     -->
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.28</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.9</version>
        </dependency>
		<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.62</version>
        </dependency>

三,实现代码

package com.lmc.excel.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import freemarker.template.TemplateException;
import sun.misc.BASE64Decoder;

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

/**
 * @ClassName: EchartsUtil
 * @author: Leemon
 * @Description: TODO
 * @date: 2021/6/14 15:43
 * @version: 1.0
 */
public class EchartsUtil {
    /**
     * 临时文件夹路径
     */
    public static final String TEMP_FILE_PATH = "D:/data/echart/";
    private static final String SUCCESS_CODE = "1";

    private static final String path = EchartsUtil.class.getClassLoader().getResource("json").getPath();


    public static void main(String[] args) throws IOException, TemplateException {

        // 获取option字符串
        String option = getStringByFile(path + "/test.json");
        JSONObject object = JSONObject.parseObject(option);
        option = object.toJSONString();

        // 根据option参数,width和height生成base64编码
        String base64 = EchartsUtil.generateEchartsBase64(option, "1360", "800");

        System.out.println("BASE64:" + base64);
        generateImage(base64, TEMP_FILE_PATH, "test.png");

    }


    public static String generateEchartsBase64(String option, String width, String height) throws IOException {
        String base64 = "";
        if (option == null) {
            return base64;
        }
        option = option.replaceAll("\\s+", "");//.replaceAll("\"", "");
        JSONObject object = JSON.parseObject(option);
        object.getJSONArray("series").getJSONObject(0).put("data", Arrays.asList(120, 200, 150, 80, 70, 110, 130));
        String json = JSONObject.toJSONString(object);
        object = JSON.parseObject(json);
        // 将option字符串作为参数发送给echartsConvert服务器
        if (width == null || "".equals(width)) {
            width = "800";
        }
        if (height == null || "".equals(height)) {
            height = "400";
        }
        Map<String, String> params = new HashMap<>();
        params.put("opt", JSON.toJSONString(object));
        params.put("width", width);
        params.put("height", height);
        String response = HttpUtil.post("http://localhost:6666", params, "utf-8");
        System.err.println(response);
        // 解析echartsConvert响应
        JSONObject responseJson = JSON.parseObject(response);
        String code = responseJson.getString("code");

        // 如果echartsConvert正常返回
        if (SUCCESS_CODE.equals(code)) {
            base64 = responseJson.getString("data");
        }
        // 未正常返回
        else {
            String string = responseJson.getString("msg");
            throw new RuntimeException(string);
        }
        return base64;
    }

    /**
     * 将base64转化为图片
     * @param base64
     * @param path
     * @param fileName
     * @throws IOException
     */
    public static void generateImage(String base64, String path, String fileName) throws IOException {
        BASE64Decoder decoder = new BASE64Decoder();
        try (OutputStream out = new FileOutputStream(path + fileName)){
            // 解密
            byte[] b = decoder.decodeBuffer(base64);
            for (int i = 0; i < b.length; ++i) {
                if (b[i] < 0) {
                    b[i] += 256;
                }
            }
            out.write(b);
            out.flush();
        }
    }
    
    /**
     * 将文件转化为字符串
     * @param fileName
     * @return
     */
    public static String getStringByFile(String fileName) {
        File file = new File("D:/Java/Echart/test.json");
        FileInputStream fis = null;
        InputStreamReader isr = null;
        BufferedReader br = null;
        StringBuilder sb = new StringBuilder();
        try {
            fis = new FileInputStream(file);
            isr = new InputStreamReader(fis);
            br = new BufferedReader(isr);
            String line = null;
            while (((line = br.readLine()) != null)) {
                sb.append(line);
            }
            br.close();
            isr.close();
            fis.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            return sb.toString();
        }
    }



}

test.json

{
	"tooltip": {
		"trigger": "axis",
		"axisPointer": {
			"type": "shadow"
		}
	},
	"legend": {
		"data": [
			"直接访问",
			"邮件营销",
			"联盟广告",
			"视频广告",
			"搜索引擎",
			"百度",
			"谷歌",
			"必应",
			"其他"
		]
	},
	"grid": {
		"left": "3%",
		"right": "4%",
		"bottom": "3%",
		"containLabel": true
	},
	"xAxis": [{
		"type": "category",
		"data": [
			"周一",
			"周二",
			"周三",
			"周四",
			"周五",
			"周六",
			"周日"
		]
	}],
	"yAxis": [{
		"type": "value"
	}],
	"series": [{
			"name": "直接访问",
			"type": "bar",
			"emphasis": {
				"focus": "series"
			},
			"data": [
				320,
				332,
				301,
				334,
				390,
				330,
				320
			]
		},
		{
			"name": "邮件营销",
			"type": "bar",
			"stack": "广告",
			"emphasis": {
				"focus": "series"
			},
			"data": [
				120,
				132,
				101,
				134,
				90,
				230,
				210
			]
		},
		{
			"name": "联盟广告",
			"type": "bar",
			"stack": "广告",
			"emphasis": {
				"focus": "series"
			},
			"data": [
				220,
				182,
				191,
				234,
				290,
				330,
				310
			]
		},
		{
			"name": "视频广告",
			"type": "bar",
			"stack": "广告",
			"emphasis": {
				"focus": "series"
			},
			"data": [
				150,
				232,
				201,
				154,
				190,
				330,
				410
			]
		},
		{
			"name": "搜索引擎",
			"type": "bar",
			"data": [
				862,
				1018,
				964,
				1026,
				1679,
				1600,
				1570
			],
			"emphasis": {
				"focus": "series"
			},
			"markLine": {
				"lineStyle": {
					"type": "dashed"
				},
				"data": [
					[{
							"type": "min"
						},
						{
							"type": "max"
						}
					]
				]
			}
		},
		{
			"name": "百度",
			"type": "bar",
			"barWidth": 5,
			"stack": "搜索引擎",
			"emphasis": {
				"focus": "series"
			},
			"data": [
				620,
				732,
				701,
				734,
				1090,
				1130,
				1120
			]
		},
		{
			"name": "谷歌",
			"type": "bar",
			"stack": "搜索引擎",
			"emphasis": {
				"focus": "series"
			},
			"data": [
				120,
				132,
				101,
				134,
				290,
				230,
				220
			]
		},
		{
			"name": "必应",
			"type": "bar",
			"stack": "搜索引擎",
			"emphasis": {
				"focus": "series"
			},
			"data": [
				60,
				72,
				71,
				74,
				190,
				130,
				110
			]
		},
		{
			"name": "其他",
			"type": "bar",
			"stack": "搜索引擎",
			"emphasis": {
				"focus": "series"
			},
			"data": [
				62,
				82,
				91,
				84,
				109,
				110,
				120
			]
		}
	]
}

运行main函数,将会在 D:/data/echart/下生成 test.png 的堆栈柱状图。

Java通过后台导出Echart图片

四,传入参数方式

前面这种方式直接把test.json中整一个文件当做一个option,这样的话数据就是写死的方式,如果需要自定义数据的话,可以通过编辑json修改option

		// 获取option字符串
        String option = getStringByFile(path + "/test.json");
        JSONObject object = JSONObject.parseObject(option);
        object.getJSONObject("legend").put("data", Arrays.asList("直接访问","邮件营销","联盟广告","其他"));
        option = object.toJSONString();

以上就是关于只通过后台生成Echart图表的方式。

上一篇:数据展示与文件读写


下一篇:Roland SRX Series for Mac - 罗兰SRX系列音频插件合集