1、所需工具

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

2》EChartConvert:https://gitee.com/saintlee/echartsconvert

2、Maven依赖

    <dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.28</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.7</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.56</version>
</dependency>

3、使用phantomjs装载运行EChartConvert

1》phantomjs、EChartConvert解压即可使用

解压 phantomjs-2.1.1-windows.zip 和 saintlee-echartsconvert-master.zip。配置phantomjs环境变量。

命令行输入:<phantomjs路径> <EChartsConvert路径> -s -p <服务端口号>
Microsoft Windows [版本 6.1.]
版权所有 (c) Microsoft Corporation。保留所有权利。 C:\fyliu\software\phantomjs-2.1.-windows\echartsconvert-gitee>phantomjs echarts
-convert.js -s -p
echarts-convert server start success. [pid]=

4、项目目录结构

1》HttpUtil.java

package com.lfy.cn.PhantomJSEChartsTest.util;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry; import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils; public class HttpUtil { public static String post(String url, Map<String, String> params, String charset)
throws ClientProtocolException, IOException {
String responseEntity = ""; // 创建CloseableHttpClient对象
CloseableHttpClient client = HttpClients.createDefault(); // 创建post方式请求对象
HttpPost httpPost = new HttpPost(url); // 生成请求参数
List<NameValuePair> nameValuePairs = new ArrayList<>();
if (params != null) {
for (Entry<String, String> entry : params.entrySet()) {
nameValuePairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
} // 将参数添加到post请求中
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, charset)); // 发送请求,获取结果(同步阻塞)
CloseableHttpResponse response = client.execute(httpPost); // 获取响应实体
HttpEntity entity = response.getEntity();
if (entity != null) {
// 按指定编码转换结果实体为String类型
responseEntity = EntityUtils.toString(entity, charset);
} // 释放资源
EntityUtils.consume(entity);
response.close(); return responseEntity;
}
}

2》FreemarkerUtil.java

package com.lfy.cn.PhantomJSEChartsTest.util;

import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Map; import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException; public class FreemarkerUtil {
private static final String path = FreemarkerUtil.class.getClassLoader().getResource("").getPath(); public static String generateString(String templateFileName, String templateDirectory, Map<String, Object> datas)
throws IOException, TemplateException {
Configuration configuration = new Configuration(Configuration.VERSION_2_3_0); // 设置默认编码
configuration.setDefaultEncoding("UTF-8"); // 设置模板所在文件夹
configuration.setDirectoryForTemplateLoading(new File(path + templateDirectory)); // 生成模板对象
Template template = configuration.getTemplate(templateFileName); // 将datas写入模板并返回
try (StringWriter stringWriter = new StringWriter()) {
template.process(datas, stringWriter);
stringWriter.flush();
return stringWriter.getBuffer().toString();
}
}
}

3》EchartsUtil.java

package com.lfy.cn.PhantomJSEChartsTest.util;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map; import org.apache.http.client.ClientProtocolException; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject; public class EchartsUtil {
private static String url = "http://localhost:6666";
private static final String SUCCESS_CODE = "1"; public static String generateEchartsBase64(String option) throws ClientProtocolException, IOException {
String base64 = "";
if (option == null) {
return base64;
}
option = option.replaceAll("\\s+", "").replaceAll("\"", "'"); // 将option字符串作为参数发送给echartsConvert服务器
Map<String, String> params = new HashMap<>();
params.put("opt", option);
String response = HttpUtil.post(url, params, "utf-8"); // 解析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;
}
}

option.ftl

{
title: {
text:'${title}',
x:'middle',
textAlign:'center'
},
xAxis: {
type: 'category',
data: ${categories}
},
yAxis: {
type: 'value'
},
series: [{
data: ${values},
type: 'bar'
}]
}

App.java

package com.lfy.cn.PhantomJSEChartsTest;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap; import org.apache.http.client.ClientProtocolException; import com.alibaba.fastjson.JSON;
import com.lfy.cn.PhantomJSEChartsTest.util.EchartsUtil;
import com.lfy.cn.PhantomJSEChartsTest.util.FreemarkerUtil; import freemarker.template.TemplateException;
import sun.misc.BASE64Decoder; public class App {
public static void main(String[] args) throws ClientProtocolException, IOException, TemplateException {
// 变量
String title = "水果";
String[] categories = new String[] { "苹果", "香蕉", "西瓜" };
int[] values = new int[] { 3, 2, 1 }; // 模板参数
HashMap<String, Object> datas = new HashMap<>();
datas.put("categories", JSON.toJSONString(categories));
datas.put("values", JSON.toJSONString(values));
datas.put("title", title); // 生成option字符串
String option = FreemarkerUtil.generateString("option.ftl", "/com/lfy/cn/PhantomJSEChartsTest/template", datas); // 根据option参数
String base64 = EchartsUtil.generateEchartsBase64(option); System.out.println("BASE64:" + base64);
generateImage(base64, "C:/Users/lfy/Desktop/test.png");
} public static void generateImage(String base64, String path) throws IOException {
BASE64Decoder decoder = new BASE64Decoder();
try (OutputStream out = new FileOutputStream(path)){
// 解密
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();
}
}
}

运行结果:生成一张ECharts图片

注:本文出自https://www.jianshu.com/p/dfc28fd7d786,支持原创。

Java - PhantomJS + EChartsConvert实现ECharts图片保存到服务端的更多相关文章

  1. ASP.NET Core单文件和多文件上传并保存到服务端

    前言: 在我们日常开发中,关于图片,视频,音频,文档等相关文件上传并保存到服务端中是非常常见的一个功能,今天主要是把自己在开发中常用的两种方式记录下来方便一下直接使用,并且希望能够帮助到有需要的同学! ...

  2. miniui datagrid 保存到服务端,使用.NET 自带 JSON 转换时发现日期格式不兼容。

    使用 miniui datagrid 修改表格后,保存到服务端,然后使用 .NET 自带 JSON 转换,会抛出DateTime 内容“2015-12-27T11:02:28”未按 JSON 的要求以 ...

  3. php+tcpdf如何把生成的pdf文件保存在服务端

    tcpdf组件目前应用得非常广泛,但是对于如何把生成的pdf文件自动保存在服务端却很少有人提及.让我们先来看看标准输出代码:   //服务器存档模式 $pdf->Output('output.p ...

  4. TCP客户端图片上传服务端保存本地示例

    //TCP客户端public class TCPClient { public static void main(String[] args)throws IOException { Socket s ...

  5. java基于socket的网络通信,实现一个服务端多个客户端的群聊,传输文件功能,界面使用Swing

    最近在复习java的io流及网络编程.但复习写那些样板程序总是乏味的.便准备写个项目来巩固.想来想去还是聊天项目比较好玩.如果日后完成的比较好自己也可以用(哈哈哈).并且自己后面也要继续巩固java多 ...

  6. android-HttpClient上传信息(包括图片)到服务端

    需要下载apache公司下的HttpComponents项目下的HTTPCLIENT ----------地址为http://hc.apache.org/downloads.cgi 主要是用到了htt ...

  7. 微信小程序开发之多图片上传+服务端接收

    前言: 业务需求,这次需要做一个小程序同时选中三张图片一起上传到服务端,后端使用的.NET WEBAPI接收数据保存. 使用技术: 在这章中将会使用到微信小程序wx.uploadFile(Object ...

  8. java 网络编程基础 TCP/IP协议:服务端ServerSocket;客户端Socket; 采用多线程方式处理网络请求

    1.Java中客户端和服务器端通信的简单实例 Java中能接收其他通信实体连接请求的类是ServerSocket,ServerSocket对象用于监听来自客户端的Socket连接,如果没有连接,它将一 ...

  9. JAVA学习第六十三课 — 关于client服务端 &amp;&amp; URL类 &amp; URLConnection

    常见的client和服务端 client:       浏览器:IE:弹窗体,猎豹:弹窗体.多标签,争强效果 服务端:       server:TomCat:1.处理请求 2.给予应答 想让TomC ...

随机推荐

  1. 【LuoguP5289】[十二省联考2019] 皮配

    题目链接 题目描述 略 Sol 一道背包问题 首先暴力做法设 \(dp[i][j][k]\) 表示前 \(i\) 个城市的学校被分到第一阵营 \(j\) 人 第一门派 \(k\) 人的方案数. 中间一 ...

  2. Linux缺少动态连接库.so--cannot open shared object file: No such file or directory

    1 Liunx安装报错时,缺少动态链接库时,形式如下: /usr/local/libexec/gcc/x86_64-unknown-liunx-gnu/4.8.2/cc1: error while l ...

  3. 6.LINUX32位和64位系统的区别和选择

  4. mysql ALTER TABLE语句 语法

    mysql ALTER TABLE语句 语法 作用:用于在已有的表中添加.修改或删除列.无铁芯直线电机 语法:添加列:ALTER TABLE table_name ADD column_name da ...

  5. codevs 1020 孪生蜘蛛 x

    题目描述 Description 在G城保卫战中,超级孪生蜘蛛Phantom001和Phantom002作为第三层防卫被派往守护内城南端一带极为隐秘的通道. 根据防护中心的消息,敌方已经有一只特种飞蛾 ...

  6. AtCoder AGC002E Candy Piles (博弈论)

    神仙题..表示自己智商不够想不到... 好几次读成最后拿的赢了,导致一直没看懂题解... 题目链接: https://atcoder.jp/contests/agc002/tasks/agc002_e ...

  7. [BZOJ3453]tyvj 1858 XLkxc:拉格朗日插值

    分析 之前一直不知道拉格朗日插值是干什么用的,只会做模板题,做了这道题才明白这个神奇算法的用法. 由题意可知,\(f(x)\)是关于\(x\)的\(k+1\)次函数,\(g(x)\)是关于\(x\)的 ...

  8. easyui 功能列传递一行数据

    DeleteRow(' + JSON.stringify(row).replace(/"/g, '"') + ',0,' + Pindex + ',' + index + ')

  9. [UPC10525]:Dove打扑克(暴力+模拟)

    题目描述 $Dove$和$Cicada$是好朋友,他们经常在一起打扑克来消遣时光,但是他们打的扑克有不同的玩法. 最开始时,牌桌上会有$n$个牌堆,每个牌堆有且仅有一张牌,第$i$个牌堆里里里那个扑克 ...

  10. ali之monkey学习

    monkey主要用来进行压力测试,稳定性测试 http://www.cnblogs.com/yyangblog/archive/2011/03/10/1980068.html 1,什么是monkey ...