最近项目中做一份由HTML转换成PDF的征信报告,其中就遇到将HTML中的图表无法直接转换成PDF的尴尬问题。我们知道图片是可以转换为PDF格式的,所以首要目标就是讲图表转换为图片。(注:该项目为标准Web项目)
1、第一种生成图表的插件:Echars 官网链接:http://echarts.baidu.com/demo.html#line-marker(这里有图表实例等)
点击红色标识可下载图片
2、第二种生成图表插件:HighCharts 官网链接:http://www.hcharts.cn/demo/highcharts/line-basic
二者区别暂且不提,不过都是生成图表很方便
同样点击红色标识处
那么问题来!!!
我们将html生成pdf是自动的过程,即正常思路为在运行HTML时图表生成图片在指定路径,并利用<img src="图片所在路径"></img>标签在HTML中引入后直接转换成PDF。而不是还需要人为的点击下载。
解决方案
- 我首先想是不是可以使用一些点击事件或者其他方法使其默认将上面需要为人点击的过程变为自动点击。试了各种事件,行不通(不是无法选择路径就是不能自己点击,如果有大神弄出来望指教)。
- 查看资料许多人在使用HighCharts时提到了SVG矢量图形,该图片转换原理就是你把图表数据发送给HighCharts的服务器,服务器转换完了在传给你,里面的原理说起来简单,看起来蛮难的。于是这条路不走了。不过附上一个人的项目源码DEMO,你们可以参考下。文件下载地址:https://files.cnblogs.com/files/ysj4428/HighChartsDemo.zip里面也要改一些
- 还是搞Echarts吧,查资料使用Base64编码转换图片,具体原理你们就找度娘吧,下面贴出源码
首先是图表HTML:
说明:
- 由于我们做的项目需要,所以第88行设定一个定时器3秒后调用,你们可以用其他方法直接调用,什么AJAX啦等等。
- 第94行那一行也是框架自己封装的方法,就是能够调用一个java类的java方法,同时可以传递参数等。(老样子你们可以用ajax调用啊,servlet啊等等)。
1 <script type="text/javascript"></script> 2 <div style=" 600px; height: 280px;display:none " id="main1" ></div> 3 4 <div style=" 600px; height: 250px;" id="main"> 5 <img alt="图片走丢了" style="height: 240px;" src="http://localhost:8080/PM/FormatDoc/AhzxReport/pic/ysj.png"> 6 </div> 7 8 <script type="text/javascript"> 9 var imgURL=""; 10 var myChart = echarts.init(document.getElementById('main1')); 11 var legendData=['销售收入曲线图']; 12 var xData=['#{firstyear}','#{nextyear}','#{lastyear}']; 13 var option = { 14 title: { 15 text: '全部销售收入趋势变化分析(年)', 16 textAlign:'100px', 17 x:'center', 18 y:'-10px' 19 }, 20 color:['#5B9BD5','#ED7D31','#A5A5A5'], 21 grid: { 22 left: '3px', 23 right: '4%', 24 bottom: '5%', 25 containLabel: true 26 }, 27 tooltip: { 28 trigger: 'axis', 29 axisPointer : { // 坐标轴指示器,坐标轴触发有效 30 type : 'line' // 默认为直线,可选为:'line' | 'shadow' 31 }, 32 formatter:'{b}<br>{a0}:{c0}<br>' 33 }, 34 legend: { 35 data:legendData, 36 formatter:function (name) { 37 return name+"(年)"; 38 }, 39 right:10, 40 top:25 41 }, 42 43 toolbox: { 44 show: false 45 }, 46 xAxis: { 47 type: 'category', 48 boundaryGap: true, 49 data:xData, 50 axisTick:{ 51 inside:true 52 } 53 54 }, 55 yAxis: { 56 type: 'value', 57 name:'销售总额(万元)', 58 /*设置y轴样式*/ 59 axisTick:{ 60 show:false 61 }, 62 axisLine: { 63 lineStyle: { 64 /* color: '#D73939',*/ 65 1, 66 type: 'solid' 67 } 68 }, 69 /*设置显示y轴数据对应的水平线*/ 70 splitLine: { 71 show: true 72 }, 73 /*设置y轴显示数据为%*/ 74 axisLabel: { 75 formatter: '{value}' 76 } 77 }, 78 series: [ 79 { 80 name:'销售收入曲线图', 81 type:'line', 82 data:[#{firstsjse}, #{nextsjse}, #{lastsjse}] 83 }, 84 85 ] 86 }; 87 myChart.setOption(option); 88 setTimeout("test()", 3000); 89 function test(){ 90 imgURL = myChart.getDataURL('png');//获取base64编码 91 var obj={}; 92 obj["imgsURl"]=imgURL; 93 obj["name"]="ysj"; 94 RunJavaMethodTrans("com.xxx.app.als.formatdoc.ahzxreport.ChangeToPhoto", "PersonTaxInfo", JSON.stringify({"data":obj})); 95 96 } 97 98 </script>
java代码:
1 package com.xxx.app.als.formatdoc.ahzxreport;/*---------包名自己改----------*/ 2 3 import java.io.File; 4 import java.io.FileOutputStream; 5 import java.io.OutputStream; 6 import java.util.HashMap; 7 8 import com.xxx.are.jbo.JBOTransaction;/*-----这里是项目框架带的不用管-----*/ 9 import com.xxx.are.lang.StringX; 10 11 import sun.misc.BASE64Decoder; 12 13 public class ChangeToPhoto { 14 private HashMap<String, String> data; 15 private String imgsURl; 16 private String name; 17 18 public String PersonTaxInfo(JBOTransaction tx){/*-------------括号内参数框架带的可以去掉,只要让你的HTML调用的JAVA方法即可---------------*/ 19 if(StringX.isEmpty(imgsURl)) 20 imgsURl=this.data.get("imgsURl"); 21 if(StringX.isEmpty(name)) 22 name=this.data.get("name"); 23 //对字节数组字符串进行Base64解码并生成图片 24 if (imgsURl == null) //图像数据为空 25 return ""; 26 BASE64Decoder decoder = new BASE64Decoder(); 27 try 28 { 29 String[] url = imgsURl.split(","); 30 String u = url[1]; 31 System.out.println(u); 32 //Base64解码 33 byte[] buffer = decoder.decodeBuffer(u); 34 //生成图片 35 System.out.println(buffer); 36 //放在工作空间的位置
37 /*-------------后面是放图片的路径,你们最好加一个指定路径,我这个放在工程里面了--------------*/
37 OutputStream out = new FileOutputStream(new File("F:/Eclipsexxx/.metadata/.plugins/org.eclipse.wst.server.core/tmp1/wtpwebapps/PM/FormatDoc/AhzxReport/pic/"+name+".png")); 38 out.write(buffer); 39 out.flush(); 40 out.close(); 41 return ""; 42 } 43 catch (Exception e) 44 { 45 return ""; 46 } 47 48 } 49 50 51 public HashMap<String, String> getData() { 52 return data; 53 } 54 55 public void setData(HashMap<String, String> data) { 56 this.data = data; 57 } 58 59 public String getImgsURl() { 60 return imgsURl; 61 } 62 63 public void setImgsURl(String imgsURl) { 64 this.imgsURl = imgsURl; 65 } 66 67 68 public String getName() { 69 return name; 70 } 71 72 73 public void setName(String name) { 74 this.name = name; 75 } 76 77 }
可能遇到的问题:
许多人可能图片转换出来了,可是HTML中不显示,原因是在项目中生成的图片需要刷新整个项目图片才会出现在项目中,所以我将图片生成地址放在Tomcat中,因为Tomcat一直在刷新吧。虽然不知道原理,但是是可以的。
欢迎各界大神批评和指出不足。特别好多地方我没弄清。