使用Java调用PhantomJS动态导出ECharts图片到Word文件中


前言

最近在一个项目中遇到导出为Word文件的问题,导出Word的功能很简单,但是导出Word文件中包含数据库动态查询的统计数据而生成的Echarts图片,且导出Word的时机又是在凌晨的服务器定时执行,所以不能通过客户端访问统计页面时再去生成。

服务端语言使用Java语言,最开始考虑使用JFreeChart来生成统计图片,但是JFreeChart生成的图片很丑,且和ECharts的统计图效果截然不同。所以最终抛弃了使用JFreeChart,而采用了在服务端使用Java调用PhantomJS的指令来导出Ehcarts图片。所以主要的技术方案选型如下:

  • poi-tl,一个简单的基于Word模版生成Word的工具。
  • PhantomJS,一个基于webkit内核的无头浏览器,可在服务端程序实现加载、操作页面等功能

使用poi-tl导出Word

poi-tl介绍

使用Java导出Word通常采用的是Apache POI的库,但是使用POI来导出Word,会书写大量的段落、样式等细节代码,代码量巨大,而且不易于维护。通过poi-tl只需要制作导出的模版,服务端一行代码调用,传入模版路径和Map或者Bean即可生成Word模版,代码量大大降低,以后导出样式不满意的时候,只需要修改Word模版文件即可。

注意poi-tl只能生成docx文件,对word2007之前的doc文档则不支持。

Maven引入

<dependency>
    <groupId>com.deepoove</groupId>
    <artifactId>poi-tl</artifactId>
    <version>1.0.0</version>
</dependency>

:该包带入了POI3.16,如果系统中本身有低于3.15版本的POI,需要排除掉,否则生成Word时会报错。

demo示例

首先,制作一个用于测试的word模版,使用poi-tl的标记语法做如下标记,如下图所示:

测试word模版

然后,构造一个需要渲染的model JavaBean类,如果有多个Bean,貌似只能通过继承来复用属性,采用组合的方式是渲染不了的,代码如下:

/**
 * BaseProp
 * @author zhangxianda on 2017-06-28.
 */
public class BaseProp {
    
<span class="token keyword">protected</span> <span class="token class-name">String</span> baseProp<span class="token punctuation">;</span>

<span class="token comment">/**
 * 构造方法.
 * @param baseProp 基础属性
 */</span>
<span class="token keyword">public</span> <span class="token class-name">BaseProp</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">super</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">public</span> <span class="token class-name">String</span> <span class="token function">getBaseProp</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">return</span> baseProp<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">setBaseProp</span><span class="token punctuation">(</span><span class="token class-name">String</span> baseProp<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>baseProp <span class="token operator">=</span> baseProp<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

}

/**
 * 测试旅游信息的bean.
 * @author zhangxianda on 2017-06-28.
 */
public class Travel extends BaseProp {

    private String title;

    private String smallTitle;

    private String startDate;

    private String endDate;

    private int count;

    private double money;

    private String place1;

    private String place2;

    private PictureRenderData pic;

    /**
     * 构造方法.
     */
    public Travel() {
        super();
    }

    /*getter和setter方法.*/

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getSmallTitle() {
        return smallTitle;
    }

    public void setSmallTitle(String smallTitle) {
        this.smallTitle = smallTitle;
    }

    public String getStartDate() {
        return startDate;
    }

    public void setStartDate(String startDate) {
        this.startDate = startDate;
    }

    public String getEndDate() {
        return endDate;
    }

    public void setEndDate(String endDate) {
        this.endDate = endDate;
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }

    public String getPlace1() {
        return place1;
    }

    public void setPlace1(String place1) {
        this.place1 = place1;
    }

    public String getPlace2() {
        return place2;
    }

    public void setPlace2(String place2) {
        this.place2 = place2;
    }

    public PictureRenderData getPic() {
        return pic;
    }

    public void setPic(PictureRenderData pic) {
        this.pic = pic;
    }

}

最后,是模拟调用示例:

/**
 * poi-tl库的使用示例.
 * Created by zhangxianda on 2017/6/27.
 */
public class PoitlTest {

<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token class-name">Logger</span> log <span class="token operator">=</span> <span class="token class-name">LoggerFactory</span><span class="token punctuation">.</span><span class="token function">getLogger</span><span class="token punctuation">(</span><span class="token class-name">PoitlTest</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">/** 项目资源路径. */</span>
<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token class-name">String</span> PATH <span class="token operator">=</span> <span class="token string">"F:/poitl-test/web"</span><span class="token punctuation">;</span>

<span class="token comment">/** word模板路径. */</span>
<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token class-name">String</span> DOC_PATH <span class="token operator">=</span> PATH <span class="token operator">+</span> <span class="token string">"/template/test/test.docx"</span><span class="token punctuation">;</span>

<span class="token comment">/** 图片路径. */</span>
<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token class-name">String</span> PIC_PATH <span class="token operator">=</span> PATH <span class="token operator">+</span> <span class="token string">"/template/test/pic.png"</span><span class="token punctuation">;</span>

<span class="token comment">/** 输出文件及路径. */</span>
<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token class-name">String</span> OUTPUT_PATH <span class="token operator">=</span> <span class="token string">"G:/test/poitl_out_word.docx"</span><span class="token punctuation">;</span>

<span class="token comment">/**
 * 构造Bean型的data数据.
 * @return map
 */</span>
<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token class-name">Travel</span> <span class="token function">buildBeanData</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token class-name">Travel</span> travel <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Travel</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    travel<span class="token punctuation">.</span><span class="token function">setTitle</span><span class="token punctuation">(</span><span class="token string">"我的旅游日记"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    travel<span class="token punctuation">.</span><span class="token function">setSmallTitle</span><span class="token punctuation">(</span><span class="token string">"再写日记"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    travel<span class="token punctuation">.</span><span class="token function">setStartDate</span><span class="token punctuation">(</span><span class="token string">"2017-01-01"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    travel<span class="token punctuation">.</span><span class="token function">setEndDate</span><span class="token punctuation">(</span><span class="token string">"2017-06-28"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    travel<span class="token punctuation">.</span><span class="token function">setCount</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    travel<span class="token punctuation">.</span><span class="token function">setPlace1</span><span class="token punctuation">(</span><span class="token string">"九寨沟"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    travel<span class="token punctuation">.</span><span class="token function">setPlace2</span><span class="token punctuation">(</span><span class="token string">"天涯海角"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    travel<span class="token punctuation">.</span><span class="token function">setMoney</span><span class="token punctuation">(</span><span class="token number">1872.52</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    travel<span class="token punctuation">.</span><span class="token function">setPic</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">PictureRenderData</span><span class="token punctuation">(</span><span class="token number">600</span><span class="token punctuation">,</span> <span class="token number">400</span><span class="token punctuation">,</span> PIC_PATH<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    travel<span class="token punctuation">.</span><span class="token function">setBaseProp</span><span class="token punctuation">(</span><span class="token string">"这是"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> travel<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token comment">/**
 * main方法.
 * @param args 数组参数
 */</span>
<span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">IOException</span> <span class="token punctuation">&#123;</span>
    <span class="token class-name">XWPFTemplate</span> template <span class="token operator">=</span> <span class="token class-name">XWPFTemplate</span><span class="token punctuation">.</span><span class="token function">compile</span><span class="token punctuation">(</span>DOC_PATH<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span><span class="token function">buildBeanData</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token class-name">FileOutputStream</span> out <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">FileOutputStream</span><span class="token punctuation">(</span>OUTPUT_PATH<span class="token punctuation">)</span><span class="token punctuation">;</span>
    template<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span>out<span class="token punctuation">)</span><span class="token punctuation">;</span>
    out<span class="token punctuation">.</span><span class="token function">flush</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    out<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    template<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    log<span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string">"通过'poi-tl'导出word成功!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

}

最后,在导出的文件夹中可查看生成的word文件,如下所示:

生成的Word文件结果

Java调用PhantomJS导出Ehcarts图片

PhantomJS介绍

PhantomJS是一个基于webkit内核的无头浏览器,即没有UI界面的一个浏览器,只是其内的点击、翻页等人为相关操作需要程序设计实现。PhantomJS提供JavaScript API接口,即通过编写js程序可以直接与webkit内核交互,在此之上可以结合Java语言等,通过java调用js等相关操作,从而解决了以前c/c++才能比较好的基于webkit开发优质采集器的限制。

PhantomJS的安装配置

windows环境

如果是在windows环境下,则在官网下载解压到某个目录后,将其bin目录加入到path变量中即可。

Linux环境

如果是在Linux环境下,在官网下载解压后,同样需要将PhantomJSbin目录加入到path环境变量中,参考的命令和配置如下:

# 编辑配置文件.
vi ~/.bashrc

# 将PhantomJS的bin目录加入到PATH环境变量中.
export PHANTOMJS_HOME=/home/zxd/Documents/phantomjs-2.1.1-linux-x86_64
export PATH=${PHANTOMJS_HOME}/bin:$PATH

# 退出vi编辑器,使用source命令让刚才的配置即时生效.
source ~/.bashrc

# 测试PhantomJS是否安装成功,如果打出了版本信息,即安装成功.
phantomjs -v

demo示例

这个demo的需求是这样的,我们使用Java调用PhantomJS的指令来在服务端加载含ECharts统计的图html文件,然后调用ECharts的生成图片方法,将图片传输到Java后台最终实现保存图片到指定路径中。

首先,制作ECharts的html页面,示例页面如下代码如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>测试的ECharts数据统计图</title>
</head>
<body>
    <!-- 为 ECharts 准备一个具备大小(宽高)的 DOM -->
    <div id="main" style="width:560px; height:270px;"></div>

<script type=text/javascript src=/js/lib/jquery/jquery-1.9.1.min.js></script>
<script type=text/javascript src=/js/lib/echarts/v3/echarts.min.js></script>
<script type=text/javascript>

// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById(‘main’));

// 指定图表的配置项和数据
var option = {
title: {
text: ‘ECharts 入门示例’
},
animation: false, // 关闭动画效果
tooltip: {},
legend: {
data:[‘销量’]
},
xAxis: {
data: [“衬衫”,“羊毛衫”,“雪纺衫”,“裤子”,“高跟鞋”,“袜子”]
},
yAxis: {},
series: [{
name: ‘销量’,
type: ‘bar’,
data: [5, 20, 36, 10, 10, 20]
}]
};

// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);

/**

  • ajax传输图片信息.
    */

function postImage() {
// 向后台发起请求保存图片到指定目录.
$.ajax({
type: ‘POST’,
url: ‘/test/saveImage’,
data: {picInfo: myChart.getDataURL()},
success: function() {
console.log(‘通过post请求传输数据成功!’);
}
});
}
</script>
</body>
</html>

然后,使用Servlet来写一个服务端代码,用来获取Base64的图片信息并在后端解析保存图片,Servlet代码如下:

/**
 * 保存Echarts统计图片的Servlet.
 * @author zhangxianda on 2017-06-28.
 */
public class SaveImageServlet extends HttpServlet {

<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">long</span> serialVersionUID <span class="token operator">=</span> <span class="token number">1L</span><span class="token punctuation">;</span>

<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token class-name">Logger</span> log <span class="token operator">=</span> <span class="token class-name">LoggerFactory</span><span class="token punctuation">.</span><span class="token function">getLogger</span><span class="token punctuation">(</span><span class="token class-name">SaveImageServlet</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">/**
 * 执行获取echarts图片的post请求.
 * @param request req
 * @param response resp
 * @throws ServletException Servlet异常.
 * @throws IOException IO异常.
 */</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">doPost</span><span class="token punctuation">(</span><span class="token class-name">HttpServletRequest</span> request<span class="token punctuation">,</span> <span class="token class-name">HttpServletResponse</span> response<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">ServletException</span><span class="token punctuation">,</span> <span class="token class-name">IOException</span> <span class="token punctuation">&#123;</span>
    <span class="token comment">// 获取图片信息.</span>
    <span class="token class-name">String</span> picInfo <span class="token operator">=</span> request<span class="token punctuation">.</span><span class="token function">getParameter</span><span class="token punctuation">(</span><span class="token string">"picInfo"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token class-name">StringUtils</span><span class="token punctuation">.</span><span class="token function">isBlank</span><span class="token punctuation">(</span>picInfo<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        log<span class="token punctuation">.</span><span class="token function">error</span><span class="token punctuation">(</span><span class="token string">"picInfo为空,未从前台获取到base64图片信息!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">getAndsaveImage</span><span class="token punctuation">(</span>picInfo<span class="token punctuation">,</span> <span class="token string">"G:/test/image1.png"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token comment">/**
 * 获取并保存图片到本地.
 * @param picInfo 图片信息
 * @param imagePath 图片保存的路径
 */</span>
<span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">getAndsaveImage</span><span class="token punctuation">(</span><span class="token class-name">String</span> picInfo<span class="token punctuation">,</span> <span class="token class-name">String</span> imagePath<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token comment">// 传递过程中  "+" 变为了 " ".</span>
    <span class="token class-name">String</span> newPicInfo <span class="token operator">=</span> picInfo<span class="token punctuation">.</span><span class="token function">replaceAll</span><span class="token punctuation">(</span><span class="token string">" "</span><span class="token punctuation">,</span> <span class="token string">"+"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token class-name">String</span> picPath <span class="token operator">=</span> <span class="token function">decodeBase64</span><span class="token punctuation">(</span>newPicInfo<span class="token punctuation">,</span> <span class="token keyword">new</span> <span class="token class-name">File</span><span class="token punctuation">(</span>imagePath<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    log<span class="token punctuation">.</span><span class="token function">warn</span><span class="token punctuation">(</span><span class="token string">"从echarts中生成图片的的路径为:&#123;&#125;"</span><span class="token punctuation">,</span> picPath<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token comment">/**
 * 解析Base64位信息并输出到某个目录下面.
 * @param base64Info base64串
 * @param picPath 生成的文件路径
 * @return 文件地址
 */</span>
<span class="token keyword">private</span> <span class="token class-name">String</span> <span class="token function">decodeBase64</span><span class="token punctuation">(</span><span class="token class-name">String</span> base64Info<span class="token punctuation">,</span> <span class="token class-name">File</span> picPath<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token class-name">StringUtils</span><span class="token punctuation">.</span><span class="token function">isEmpty</span><span class="token punctuation">(</span>base64Info<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">return</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token comment">// 数据中:data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABI4AAAEsCAYAAAClh/jbAAA ...  在"base64,"之后的才是图片信息</span>
    <span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> arr <span class="token operator">=</span> base64Info<span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token string">"base64,"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token comment">// 将图片输出到系统某目录.</span>
    <span class="token class-name">OutputStream</span> out <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
    <span class="token keyword">try</span> <span class="token punctuation">&#123;</span>
        <span class="token comment">// 使用了Apache commons codec的包来解析Base64</span>
        <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> buffer <span class="token operator">=</span> <span class="token class-name">Base64</span><span class="token punctuation">.</span><span class="token function">decodeBase64</span><span class="token punctuation">(</span>arr<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        out <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">FileOutputStream</span><span class="token punctuation">(</span>picPath<span class="token punctuation">)</span><span class="token punctuation">;</span>
        out<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span>buffer<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">IOException</span> e<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        log<span class="token punctuation">.</span><span class="token function">error</span><span class="token punctuation">(</span><span class="token string">"解析Base64图片信息并保存到某目录下出错!"</span><span class="token punctuation">,</span> e<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span> <span class="token keyword">finally</span> <span class="token punctuation">&#123;</span>
        <span class="token class-name">IOUtils</span><span class="token punctuation">.</span><span class="token function">closeQuietly</span><span class="token punctuation">(</span>out<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token keyword">return</span> picPath<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

}

然后,是书写PhantomJS脚本echarts_load.js来加载和调用图片下载的代码:

var system = require('system');
var page = require('webpage').create();

// 如果是windows,设置编码为gbk,防止中文乱码,Linux本身是UTF-8
var osName = system.os.name;
console.log(‘os name:’ + osName);
if (‘windows’ === osName.toLowerCase()) {
phantom.outputEncoding=“gbk”;
}

// 获取第二个参数(即请求地址url).
var url = system.args[1];
console.log(‘url:’ + url);

// 显示控制台日志.
page.onConsoleMessage = function(msg, lineNum, sourceId) {
console.log(‘CONSOLE: ‘ + msg + ‘ (from line #’ + lineNum + ‘ in “‘ + sourceId + ‘“)’);
};

//打开给定url的页面.
var start = new Date().getTime();
page.open(url, function(status) {
if (status == ‘success’) {
console.log(‘echarts页面加载完成,加载耗时:’ + (new Date().getTime() - start) + ‘ ms’);

    <span class="token comment">// 由于echarts动画效果,延迟500毫秒确保图片渲染完毕再调用下载图片方法.</span>
    <span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        page<span class="token punctuation">.</span><span class="token function">evaluate</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token function">postImage</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"调用了echarts的下载图片功能."</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">,</span> <span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span> <span class="token keyword">else</span> <span class="token punctuation">&#123;</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"页面加载失败 Page failed to load!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token comment">// 3秒后再关闭浏览器.</span>
<span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    phantom<span class="token punctuation">.</span><span class="token function">exit</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">,</span> <span class="token number">3000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

});

最后,是使用Java来调用PhantomJS的指令,代码如下:

/**
 * HttpTest.
 * @author zhangxianda on 2017-06-28.
 * @version 1.0
 */
public class HttpTest {

<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token class-name">Logger</span> log <span class="token operator">=</span> <span class="token class-name">LoggerFactory</span><span class="token punctuation">.</span><span class="token function">getLogger</span><span class="token punctuation">(</span><span class="token class-name">HttpTest</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token class-name">String</span> PHANTOM_PATH <span class="token operator">=</span> <span class="token string">"phantomjs"</span><span class="token punctuation">;</span>

<span class="token comment">//这里我的test.js是保存在G盘下面的phantomjs目录</span>
<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token class-name">String</span> TEST_JS <span class="token operator">=</span> <span class="token string">"G:/test/phantom/test.js "</span><span class="token punctuation">;</span>

<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token class-name">String</span> <span class="token function">downloadImage</span><span class="token punctuation">(</span><span class="token class-name">String</span> url<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">IOException</span> <span class="token punctuation">&#123;</span>
    <span class="token class-name">String</span> cmdStr <span class="token operator">=</span> PHANTOM_PATH <span class="token operator">+</span> TEST_JS <span class="token operator">+</span> url<span class="token punctuation">;</span>
    log<span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string">"命令行字符串:&#123;&#125;"</span><span class="token punctuation">,</span> cmdStr<span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token class-name">Runtime</span> rt <span class="token operator">=</span> <span class="token class-name">Runtime</span><span class="token punctuation">.</span><span class="token function">getRuntime</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">try</span> <span class="token punctuation">&#123;</span>
        rt<span class="token punctuation">.</span><span class="token function">exec</span><span class="token punctuation">(</span>cmdStr<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">IOException</span> e<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        log<span class="token punctuation">.</span><span class="token function">error</span><span class="token punctuation">(</span><span class="token string">"执行phantomjs的指令失败!请检查是否安装有PhantomJs的环境或配置path路径!PhantomJs详情参考这里:http://phantomjs.org"</span><span class="token punctuation">,</span> e<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>

<span class="token comment">/**
 * main.
 * @param args args
 * @throws IOException IO异常
 */</span>
<span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">IOException</span> <span class="token punctuation">&#123;</span>
    <span class="token function">downloadImage</span><span class="token punctuation">(</span><span class="token string">"http://127.0.0.1:8080/test/echart_test/test_echarts.html"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

}

通过调用测试代码即可在指定目录生成Echarts的图片啦!

联系上面生成Word的功能,两个功能一结合即可动态导出ECharts图片到Word文件中。


文章作者: 张显达
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 张显达 !
  目录