网友结论:PhantomJS技术方案老旧,推荐使用Puppeteer, 最差也用 casperjs
自带示例:网页指定生成文件
phantomjs printmargins.js https://my.oschina.net/liuzidong myoschina.png 0 0 1000 1000
PhantomJS+Echarts生成图片
参考资料
1. ECharts - Java类库
2. SpringBoot系列 - 集成Echarts导出图片
3. base64 To File
4. Java实现网页截屏功能(图片下载功能)的几种方式(整理)
5. 基于PhantomJS+Highcharts/echarts的服务器端图表渲染方案
6. ECharts服务端渲染方案
7. 使用Java调用PhantomJS动态导出ECharts图片到Word文件中
8. java使用phantomjs进行截图
9. PhantomJS文档 腾讯
10. Phantomjs教你如何实现浏览器截图并上传截图文件 #15
11. PhantomJS在服务端生成ECharts图片
12. java后端生成echarts图片
13. Java 用 PhantomJS+ECharts 后台生成图片
14. Echarts + WebSocket实现图片生成
phantomjs
phantomjs的镜像网站
PhantomJS是一个基于webkit内核的无头浏览器,即没有UI界面的一个浏览器,只是其内的点击、翻页等人为相关操作需要程序设计实现。
PhantomJS提供JavaScript API接口,即通过编写js程序可以直接与webkit内核交互,在此之上可以结合Java语言等,通过java调用js等相关操作,从而解决了以前c/c++才能比较好的基于webkit开发优质采集器的限制。
可通过:npm install phantomjs -g 安装
检查版本:phantomjs --version
方案1: 半自动方案:ECharts+Java实现,ECharts>Base64>ToImages
直接访问:http://localhost/echarts/line.html 获取ECharts的base64自动请求url,Java后台生成图片。
优点:实现方便
不足:手工打开
方案2: 全动方案:纯Java实现,Phantomjs的API
提供url(http://localhost/echarts/createPhantomjs),Java后台调用Phantomjs的API生成图片
优点:实现方便
方案3: 使用PhantomJS在服务端生成ECharts图片
手工启动PhantomJS服务器,通过构造ECharts的Options数据调用Java生成图片。
优化点:将相关JS放置资源文件下,全部通过Java后台实现调用。
关键点
1. 环境变量配置
将phantomjs添加至环境变量中。
windows:
右键我的电脑->属性->高级系统设置->高级->环境变量->用户变量/系统变量->Path=D:\phantomjs\bin;
或
cmd->set path=%path%;D:\phantomjs\bin
linux:
vi /etc/profile
export PATH=$PATH:/usr/phantomjs/bin
2. application.properties配置
phantomjs.exec.path=D:/phantomjs-2.1.1-windows/bin/phantomjs
# 通过调用myChart.getDataURL()得到base64,调用java直接生成图片,适用于不复杂的场景
phantomjs.echarts.get.base64.call.java.url=http://localhost/echarts/line.html
phantomjs.call.java.url=http://localhost/echarts/phantomjs
image.root.path=D:/images
image.width=850
image.height=850
3. Java配置
1、拼接cmd命令并执行>启动服务
private static String getCmd() throws FileNotFoundException {
StringBuilder cmd = new StringBuilder();
cmd.append("D:/phantomjs-2.1.1-windows/bin/phantomjs").append(SP);
cmd.append(getEchartsRootPath() + "/echarts-convert.js").append(SP);
cmd.append("-s").append(SP);
return cmd.toString();
}
private static String getEchartsRootPath() throws FileNotFoundException {
return ResourceUtils.getFile("classpath:phantomjs/echarts").getAbsolutePath();
}
public static void startPhantomjs() throws FileNotFoundException {
Runtime rt = Runtime.getRuntime();
String cmdStr = getCmd();
log.info("执行命令:{}", cmdStr);
try {
rt.exec(cmdStr);
} catch (IOException e) {
log.error("执行phantomjs的指令失败!请检查是否安装有PhantomJs的环境或配置path路径!PhantomJs详情参考这里:http://phantomjs.org", e);
}
log.info("打开地址完成!");
}
2、拼接ECharts的Options,调用HttpClients的API生成。
private static void createImage() throws Exception {
//
String url = "http://localhost:9090";
// 不必要的空格最好删除,字符串请求过程中会将空格转码成+号
String optJson = "{title:{text:'ECharts 示例'},tooltip:{},legend:{data:['销量']},"
+ "xAxis:{data:['衬衫','羊毛衫','雪纺衫','裤子','高跟鞋','袜子']},yAxis:{},"
+ "series:[{name:'销量',type:'bar',data:[5,20,36,10,10,20]}]}";
Map map = new HashMap<>();
map.put("opt", optJson);
map.put("echartsRoot", getEchartsRootPath());
try {
String post = post(url, map, "utf-8");
System.out.println(post);
Map jsonMap = new Gson().fromJson(post, Map.class);
String base64Info = (String) jsonMap.get("data");
Base64ImgsUtil.base64StringToImage(base64Info, "D:\\images\\" + UUID.randomUUID().toString() + ".png");
} catch (ParseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
// post请求
public static String post(String url, Map map, String encoding) throws ParseException, IOException {
String body = "";
// 创建httpclient对象
CloseableHttpClient client = HttpClients.createDefault();
// 创建post方式请求对象
HttpPost httpPost = new HttpPost(url);
// 装填参数
List nvps = new ArrayList<>();
if (map != null) {
for (Entry entry : map.entrySet()) {
nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
}
// 设置参数到请求对象中
httpPost.setEntity(new UrlEncodedFormEntity(nvps, encoding));
// 执行请求操作,并拿到结果(同步阻塞)
CloseableHttpResponse response = client.execute(httpPost);
// 获取结果实体
HttpEntity entity = response.getEntity();
if (entity != null) {
// 按指定编码转换结果实体为String类型
body = EntityUtils.toString(entity, encoding);
}
EntityUtils.consume(entity);
// 释放链接
response.close();
return body;
}