使用phantomjs实现highcharts等报表通过邮件发送(本文仅提供完整解决方案和实现思路,完全照搬不去整理代码无法马上得到效果)

 

前不久项目组需要将测试相关的质量数据通过每日自动生成报表展示,并自动通过将报表作为邮件正文内容知会到干系人邮箱。那么问题来了,报表生成了,但是邮件怎么发送,因为highcharts等报表都是通过JS和HTML在前端浏览器进行渲染生成的,而最要命的是邮箱为了安全起见一般都不支持JS,所以就算后台计算出了报表所需的数据,但是也无法在邮件内容中生成报表。 后来想到phantomjs这个神器,它是一个基于webkit的内核浏览器,可以不弹出浏览器界面在内存中模拟打开网页,进而加载需要的东东(当然包括highchars等依靠JS生成的报表渲染);  于是采用以下解决方案

1. 用JAVA从数据库查询出报表需要的各种数据

2. 在服务器通过JAVA跨进程调用phantomjs启动进程打开指定的URL,加载和渲染highchars报表

3. 等待若干秒,渲染完highchars报表后,调用phantomjs的网页截屏功能,将当然网页内容(报表内容)截图保存成一个指定URI的图片PNG或者JPG,保存到服务器某个指定目录

4. 在邮件中直接用<img src="服务器上保存的报表图片URI"> 进行引用加载图片

相关参考代码:

1. 新建你的JAVA类,发送邮件主JAVA方法:

。。。。用java去数据库取出报表所需数据,省略。。。

// 初始化趋势图片

ServletContext servletContext = ContextLoaderListener.getCurrentWebApplicationContext().getServletContext();
String ip = "IP";
int port = 8080;
String contextPath = servletContext.getContextPath();

String url =
"http://" + ip + ":" + port + contextPath + "/" + "router.do?service=testReport.testReportChart";

rootMap.put("chartUrl", url);

// String outfile = "/images"+contextPath+"/testReportChart/"+new Date().getTime()+"_"+new
// Random().nextInt(9999)+".png" ;

SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmSS");
Date date = new Date();
String outfile_suffix =
"testReportChart/" + sdf.format(date) + date.getTime() + "_" + new Random().nextInt(9999) + ".png";

String outfile = "/xxx路径/apache-tomcat-7.0.54/webapps/ROOT/" + outfile_suffix;
String outfileUrl = "http://" + ip + ":" + port + "/" + outfile_suffix;

// phantomjs文件存放位置
String infile = servletContext.getRealPath("/") + "js/phantomjs/capture.js";

try
{

//PhantomjsUtil.initHighchartImage为调用phantomjs并返回结果   infile为phantomjs脚本文件,outfile为phantomjs生成图片后保存的服务器URI
   if ("success".equalsIgnoreCase(PhantomjsUtil.initHighchartImage(infile, url, outfile)))
   {
        rootMap.put("count404Image", outfileUrl);

}
else
{
// 默认图片
rootMap.put("count404Image", "http://URL/1208_tOl.gif");
}
}
catch (Exception e)
{
// 默认图片
rootMap.put("count404Image", "http://url/1208_tOl.gif");
e.printStackTrace();
}

。。。

result = testReportService.sendTemplateMail(rootMap, from, toEmail, cc, subject, templateName);

}

2.新建JAVA类PhantomjsUtil.java实现phantomjs调用(确保服务器上安装好了phantomjs以及配置好环境变量)

package com.vipshop.util.hcharts.svg;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class PhantomjsUtil
{

/**
* @author sea.zeng
* @param infile String infile = " d:/phantomjs/capture.js " ;
* @param url String url = " http://ip:8080/xxx/router.do?service=xxxReport.xxxReportChart " ;
* @param outfile String outfile = " D:/phantomjs/testReportChart"+new Date().getTime()+"_"+new
* Random().nextInt(9999)+".png" ;
* @return String fail success
* @throws IOException
*/
public static String initHighchartImage(String infile, String url, String outfile)
throws IOException
{
String shell = " phantomjs ";

Runtime rt = Runtime.getRuntime();
Process p = rt.exec(shell + " " + infile + " " + url + " " + outfile);
InputStream is = p.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
StringBuffer sbf = new StringBuffer();
String tmp = "";

while ((tmp = br.readLine()) != null)
{
sbf.append(tmp);
}

  return sbf.toString();

}

}

3. 新建phantomjs的脚本文件capture.js并存放到指定目录js/phantomjs/下

var page = require(‘webpage‘).create(); 
var system = require(‘system‘) ;
var url = system.args[1];
var outUri = system.args[2];

page.viewportSize = { width: 1400, height: 450 };
page.open(url, function (status) {
if (status !== ‘success‘) {
console.log(‘fail‘);
} else {
window.setTimeout(function () {
console.log(‘success‘); 
page.render(outUri);
phantom.exit();
}, 10000);
}
});

4. highchars图表定义文件testReport_chart.ftl

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>xxxx趋势图</title>

<script type="text/javascript" src="http://${rootMap.ip}:${rootMap.port}/xxx/js/jquery-1.8.3.min.js"></script>
<script type="text/javascript" src="http://${rootMap.ip}:${rootMap.port}/xxx/js/highcharts.js"></script>
<script type="text/javascript" src="http://${rootMap.ip}:${rootMap.port}/xxx/js/exporting.js"></script>
<script type="text/javascript" src="http://${rootMap.ip}:${rootMap.port}/xxx/js/highcharts-3d.js"></script>
<script>

</script>

</head>

<body>

<div id="container" style="min-width:700px;height:400px"></div>

</body>

</html>

<script>

function initHighCharts(newCountArray,closeCountArray,datesArray)
{

var closeDate = datesArray;

var closeArray = eval(‘([‘ + closeCountArray + ‘])‘);

var newArray = eval(‘([‘ + newCountArray + ‘])‘);

$(‘#container‘).highcharts({
chart: {
type: ‘line
},
title: {
text: ‘缺陷日新增与日关闭趋势图‘
},
subtitle: {
text: ‘App-特卖会‘
},
xAxis: {
/*categories: [‘Jan‘, ‘Feb‘, ‘Mar‘, ‘Apr‘, ‘May‘, ‘Jun‘, ‘Jul‘, ‘Aug‘, ‘Sep‘, ‘Oct‘, ‘Nov‘, ‘Dec‘]*/
categories:closeDate 
},
yAxis: {
title: {
text: ‘单位 (个)‘
}
},
tooltip: {
enabled: false,
formatter: function() {
return ‘<b>‘+ this.series.name +‘</b><br/>‘+this.x +‘: ‘+ this.y +‘°C‘;
}
},
plotOptions: {
line: {
dataLabels: {
enabled: true
},
enableMouseTracking: false
}
},
series: [{
name: ‘日新增‘,
data: newArray
}, {
name: ‘日关闭‘,
data: closeArray
}]

});
}

//异步得到需要的版本统计数据 
function queryCountList()
{

var version = $(‘#version‘).val();
if( isEmpty(version))
{

alert("不要偷懒,请先选择版本吧...");
document.getElementById(‘version‘).focus();
return false;
}

$.post("bugzillapost.php", 
{
methodType:‘queryCountList‘,
version:version
}, 
function(data)
{

$("#content").html("");

var obj = JSON.parse(data);

if (obj.bugzillaCountList != undefined )
{

var bugzillaCountList = JSON.parse(obj.bugzillaCountList);

var trHtml = ‘‘ ;

if(null != bugzillaCountList && bugzillaCountList.length > 0)
{

for(var i=0;i < bugzillaCountList.length;i ++ )
{

var trClass = (i%2 == 0) ?"odd":"even" ;
trHtml += ‘<tr class=\"‘+trClass+‘\">‘;
trHtml += ‘<td >‘+(i+1)+‘</td>‘;
trHtml += ‘<td >‘+bugzillaCountList[i].rep_platform+‘</td>‘ ;
trHtml += ‘<td >‘+bugzillaCountList[i].op_sys+‘</td>‘;
trHtml += ‘<td >‘+bugzillaCountList[i].bug_severity+‘</td>‘ ;
trHtml += ‘<td >‘+bugzillaCountList[i].today_new+‘</td>‘ ;
trHtml += ‘<td >‘+bugzillaCountList[i].today_close+‘</td>‘ ;
trHtml += ‘<td >‘+bugzillaCountList[i].today_reopen+‘</td>‘ ;
trHtml += ‘<td >‘+bugzillaCountList[i].total_reopen+‘</td>‘ ;
trHtml += ‘<td >‘+bugzillaCountList[i].to_fix+‘</td>‘ ;
trHtml += ‘<td >‘+bugzillaCountList[i].to_reg+‘</td>‘ ;
trHtml += ‘<td >‘+bugzillaCountList[i].closed+‘</td>‘ ;
trHtml += ‘<td >‘+bugzillaCountList[i].sub_total+‘</td>‘ ;
trHtml += ‘ </tr>‘;

}

$("#content").prepend (trHtml);
$(‘table[id$="tableItem"]‘).find("tr").bind(‘click‘,function(event){
$(‘table[id$="tableItem"]‘).find("tr").removeClass("selected");
$(this).addClass("selected");
});

}

}

var newCountArray = JSON.parse(obj.newCountArray);
var closeCountArray = JSON.parse(obj.closeCountArray);
var datesArray = JSON.parse(obj.datesArray);

//newCountArray,closeCountArray,datesArray为异步从后台数据查出的数组,这里先异步从PHP或者JAVA去数据库取数据
initHighCharts(newCountArray,closeCountArray,datesArray);

});

}

</script>

5. 邮件通过报表图片服务器的URL直接引用截图保存后的报表

<h3><strong>附图. xxxx趋势图<span style="font-size:12px">(<a href="${rootMap.chartUrl}" target="_blank">点击查看详细趋势图</a>)</span></strong></h3> 
<div>
<img src = "${rootMap.countImage}" /> 
</div>

本着资源共享的原则,欢迎各位朋友在此基础上完善,并进一步分享,让我们的实现更加优雅。如果有任何疑问和需要进一步交流可以加我QQ 1922003019或者直接发送QQ邮件给我沟通

使用phantomjs实现highcharts等报表通过邮件发送的更多相关文章

  1. 使用phantomjs实现highcharts等报表通过邮件发送(本文仅提供完整解决方案和实现思路,完全照搬不去整理代码无法马上得到效果)

    前不久项目组需要将测试相关的质量数据通过每日自动生成报表展示,并自动通过将报表作为邮件正文内容知会到干系人邮箱.那么问题来了,报表生成了,但是邮件怎么发送,因为highcharts等报表都是通过JS和 ...

  2. 利用PhantomJS搭建Highcharts export服务

    利用PhantomJS搭建Highcharts export服务 一直在使用Highcharts做web图表的展示, 但是当发送定时的报表邮件的遇到了这个问题. 为了保证邮件图表和web页图表样式一致 ...

  3. Highcharts图形报表的简单使用

    Highcharts是一个纯JavaScript框架,与MSChart完全不一样,可以在网页中使用,所以php.asp.net.jsp等等页面中都可以使用.Highcharts官网:http://ww ...

  4. Zabbix通过邮件发送Screen图形报表实现

    在使用Zabbix的过程中,我们通常会建立一些需要的Screen图形报表来汇总需要监控的Graph. 而下面的两个脚本,则是通过从Zabbix数据库中获取所有的Screen图形参数,提供Zabbix的 ...

  5. jenkins 生成HTML报表,邮件推送

    1.登录jenkins,系统管理=>插件管理 =>可选插件安装 安装成功: 2.打开任务,进入配置 3.添加构建后操作 4.配置页面 5.构建后report输出配置完成后点击立即构建,构建 ...

  6. Java实现多线程邮件发送

    利用java多线程技术配合线程池实现多任务邮件发送. 1.基本邮件发送MailSender package hk.buttonwood.ops.email; import java.io.File; ...

  7. 用Python实现邮件发送Hive明细数据

    代码地址如下:http://www.demodashi.com/demo/12673.html 一.需求描述 客户需要每周周一接收特定的活动数据,生成Excel或是CSV文件,并通过邮件发送给指定接收 ...

  8. java mail邮件发送(带附件) 支持SSL

    java mail邮件发送(带附件)有三个类 MailSenderInfo.java package mail; import java.util.Properties; import java.ut ...

  9. 玩转 SpringBoot2.x 之整合邮件发送

    序 在实际项目中,经常需要用到邮件通知功能.比如,用户通过邮件注册,通过邮件找回密码等:又比如通过邮件发送系统情况,通过邮件发送报表信息等等,实际应用场景很多. 原文地址:https://www.mm ...

随机推荐

  1. iOS7之定制View Controller切换效果

    在iOS5和iOS6前,View Controller的切换主要有4种: 1. Push/Pop,NavigationViewController常干的事儿 2. Tab,TabViewControl ...

  2. 十二、BOOL冒泡

    int main(){        int a[5] = {5,2,3,4,1};      //需要一个可以告诉我们没有交换的东西      //YES:交换      //NO:未交换     ...

  3. 你用什么方法检查 PHP 脚本的执行效率(通常是脚本执行时间)和数据库 SQL 的效率(通常是数据库 Query 时间), 并定位和分析脚本执行和数据库查询的瓶颈所在?

    php: 一般是在你要检查的代码开头记录一个时间,结尾记录一个时间.取差值, 数据库SQL的效率    sql的explain(mysql),启用slow query log记录慢查询.   通常还要 ...

  4. 《自学C语言》初级教程 - 目录

    我现在打算出一个C语言学习教程,目的是为了让初学者能够很容易和更深刻地理解C语言. 你可能有这样的疑问,网上不是有很多的初级教程吗,我需要这个吗?我的回答是:网上的C语言教程讲得不够全面,而且许多的初 ...

  5. 使用IE10登录,URL出现SessionId的解决办法

    问题:用户登入之后,URL会出现一长串字符,类似SessionId,把这一长串字符删除之后重新进入页面,页面又会自动地跳转到登录页面,所以,应该是Session没记住用户已经登录的信息. 网站环境: ...

  6. python学习小结8:I/O

    文件I/O是Python中最重要的技术之一,在Python中对文件进行I/O操作是非常简单的. 打印到屏幕上 >>> print "python is really a g ...

  7. iOS优化内存方法推荐

    1. 用ARC管理内存 ARC(Automatic ReferenceCounting, 自动引用计数)和iOS5一起发布,它避免了最常见的也就是经常是由于我们忘记释放内存所造成的内存泄露.它自动为你 ...

  8. WPF 多线程处理(4)

    WPF 多线程处理(1) WPF 多线程处理(2) WPF 多线程处理(3) WPF 多线程处理(4) WPF 多线程处理(5) WPF 多线程处理(6) 开始一个线程处理读取的文件并且更新到list ...

  9. .NET核心代码保护策略-隐藏核心程序集

    经过之前那个道德指责风波过后也有一段时间没写博客了,当然不是我心怀内疚才这么久不写,纯粹是程序员的通病..怎一个懒字了得,本来想写一些长篇大论反讽一下那些道德高人的.想想还是算了,那样估计会引来新一波 ...

  10. Google history

    传说,硅谷的公司在和微软的竞争中一直处于下风,不论在市场,人才,还是在打官司上,直到婴儿巨人Baby Giant谷歌的出现,历史才出现前所未有的改变.Google以一个强大的挑战者的身份出现在人们的视 ...