1 网页端echarts图片显示后,图片上传到后端
下面我自定义了一个回调callback方法,是为了上传完了想做其他的事情
setTimeout(function(){
genPic(callback);
},2000);
function genPic(callback){
var data = "pic="+encodeURIComponent(mainChart.getDataURL("png"));
var xmlhttp;
if (window.XMLHttpRequest) { // code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
} else { // code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.open("POST",ctx+"/productDetail/genNetPic?fundId="+$('#netfundId').val(),true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
// 回调生成结果
callback(true);
} else if (xmlhttp.status!=200){
callback(false);
}
}
xmlhttp.send(data);
}
2 controller中生成图片并保存到本地
@RequestMapping(value = "genNetPic", method = RequestMethod.POST)
@ResponseBody
public BaseResponse genNetPic(HttpServletRequest request){
logger.info("开始生成净值分析的图片");
String pic = request.getParameter("pic");
String fundId = request.getParameter("fundId");
BaseResponse baseResponse = null;
try{
String[] url = pic.split(",");
String u = url[1];
byte[] b = new BASE64Decoder().decodeBuffer(u);
// 创建图片生成的路径:日期+产品id
Date curDate = new Date();
StringBuilder filePath = new StringBuilder("");
filePath.append(upload_path).append(DateUtil.formatDate(curDate, "yyyy-MM-dd")).append("/").append(fundId);
FileUtil.createDictionary(filePath.toString());
// 创建图片文件
OutputStream out = new FileOutputStream(new File(filePath.toString()+"/net.png"));
out.write(b);
out.flush();
out.close();
baseResponse = new BaseResponse(true);
logger.info("开始生成净值分析的结束");
} catch(Exception e){
logger.error("生成净值分析的图片失败,失败原因:{}",e.getMessage());
baseResponse = new BaseResponse(false, "净值分析图片生成失败");
}
return baseResponse;
}
3 写入图片base64字节码到vm模板中
先用word插入一张图片
然后将word转成xml格式(word2003的),这个版本好找到图片的base64字节码,将他删掉(非常长),替换为${netImage}为velocity能够识别的
最后通过下面的代码写入就可以。
params.put("netImage", writeNetImage(fundId, dateStr));
private String writeNetImage(String fundId, String dateStr){
StringBuilder fileName = new StringBuilder();
fileName.append(upload_path).append(dateStr).append("/").append(fundId).append("/net.png");
return ImageUtil.getImageStr(fileName.toString());
}
4 将参数传递到vm中,并生成word。
@RequestMapping(value = "exportReport", method = RequestMethod.GET)
public void exportReport(String fundId, String fundName, HttpServletResponse response){
Date curDate = new Date();
// 文件名
StringBuilder fileName = new StringBuilder("");
fileName.append(fundName).append("评价报告_").append(DateUtil.formatDate(curDate, "yyyy-MM-dd")).append(".doc");
// 文件路径
StringBuilder filePath = new StringBuilder("");
filePath.append(upload_path).append(fileName.toString());
try{
response.setContentType("text/plain");
response.setHeader("Content-Disposition", "attachment; filename="+FileUtil.getAttachName(fileName.toString()));
//报告中的参数
Map<String,Object> params = getReportParams(fundId, fundName, curDate);
String reportContent = VelocityUtil.genTemplateFromClass(report_vm_path, params);
File file = new File(filePath.toString());
_vm2File(file, reportContent);
// 根据内容生成文件
FileUtil.download(filePath.toString(), response.getOutputStream());
} catch (FileException e){
throw e;
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 将模板内容形成文件
* @param file
* @param content
*/
private void _vm2File(File file, String content){
FileWriter fw = null;
try {
fw = new FileWriter(file);
fw.write(content);
fw.flush();
} catch (IOException e) {
e.printStackTrace();
} finally{
if (null != fw){
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
5 前台js页面打开下载word
注意下面的写法不是直接用window.open ,防止浏览器拦截了页面的打开。
var url = ctx + '/productDetail/exportReport?fundId=' + fundId + '&fundName=' + fundName;
var tempwindow=window.open("");
tempwindow.location=url;
6 总结
虽然velocity、freemarker能够生成word,模板内容量太大了,全是xml节点,看看下图就知道了,后期基本无法维护,故虽然技术上可行,但还是不要使用。建议还是采用报表工具。