Java - PhantomJS + EChartsConvert实现ECharts图片保存到服务端
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.7601] 版权所有 (c) 2009 Microsoft Corporation。保留所有权利。 C:\fyliu\software\phantomjs-2.1.1-windows\echartsconvert-gitee>phantomjs echarts -convert.js -s -p 6666 echarts-convert server start success. [pid]=2284
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,支持原创。