使用flying sauser +velocity 导出文字+表格+echars图表为PDF
首先介绍一下项目背景,项目框架是spring,按照网页上成熟的样式把包含文字、表格、echarts的内容导出为PDF,考虑到网页上的样式是成熟的,所以使用flying sauser 来解析html和css,在做项目之前 看网上很多人都推荐用这个,但是实际用起来并不是很顺手啊,毕竟不是浏览器啊 ,貌似只能解析css2.0版本的,且很多地方解析出来的展现效果都跟浏览器不一样 比如说写一个table标签 如果你不给table加style样式的 表格根本不展示出来。原网页是vm模板,所以直接使用velocity engine ,动态数据使用一个map传进去,merge一下就得到最终的html+css了 交给flying sauser去解析就好了
大概说一下项目难点:
第一点,原网页不能完全照搬 ,一般情况下原网页上的css和js都是外联的,flying sauser是肯定不能解析的,js外联直接删掉,css想解析就拿出来直接贴在网页文件上,所有的js代码块都删掉。然后这样传进去展现出来的效果肯定跟浏览器不一样,很多地方错位啊 看着惨不忍睹,所以就开始对网页进行琐碎的修修改改了 就是调样式 不知道为啥,中文的左边如果没有非中文字符他就不显示,所以我在纯中文的地方都在左边加了一个 (空格)反正调样式这块真的很烦人,因为他完全不按常理出牌啊,同样的代码在浏览器那边能好好展示,他就不行。反正我在他这遇到了好多问题,中文不显示不占位啦导致格式错位,td里内容不自动换行,img标签传入base64编码他完全不认。。。。。。td内容不自动换行,一般解决方法就是加word-break,浏览器展现肯定没问题,可是flying sauser就不行啦,他只能解析css2.0的属性,word-break什么鬼 人家不知道啦
第二点,echarts图表的导出 echarts本身有个方法 getDataURL()这个方法能获得图表图片格式的base64编码,这个值可以传给img标签的src属性就能展示啦 但是上面说flying sauser他并不支持img标签的src这种写法 所以要对flying sauser做一些修改才能支持
代码display:先从前端页面开始。
//导出
<script>
jQuery(function() {
jQuery("#export").click(function(){
jQuery("#a").val(myChart.getDataURL("png"));
jQuery("#fundAccountFlowForm").attr("action","export/stockholder-hold.htm");
jQuery("#fundAccountFlowForm").submit();
});
});
</script>
<td><input type="button" id="export" value="导出" class="but-61" /></td>
<input type="hidden" name="a" id="a"/>
//echarts图表的容器div
<div id="chart" style="width: 600px;height:400px;"></div>
<script type="text/javascript">
var myChart = echarts.init(document.getElementById('chart'));
option={
//省略echarts的配置
};
//为echarts对象加载数据
myChart.setOption(option);
</script>
代码display:前端页面传到后台spring controller
@RequestMapping("export/stockholder-hold.htm")
public void exportstockholder(@ModelAttribute("query") HStockHolder query, HttpServletRequest req, ModelMap model, HttpServletResponse response,String a ) {
//此处访问数据库查询数据,把获得的数据放入map,在此例中为query
//方法参数中的string a为上面前端页面中input hidden name=a的echarts图表的base64编码值
Map<String,Object> map=new HashMap<String,Object>();
map.put("imgBase64", a);
map.put("query", query);
exportPDFHelper.exportPDF(response,"报表pdf默认文件名",map,"报表的vm模板文件名");
代码display:exportPDFHelper
//调用velocity engine来融合数据和vm模板
public String mergeMessage(String vmPath, Map map) {
String text = VelocityEngineUtils.mergeTemplateIntoString(exportPDFVelocityEngine, vmPath, map);
return text;
}
public void exportPDF(HttpServletResponse response,String fileName,
Map<String,Object> map,String template) {
try{
OutputStream os = response.getOutputStream();// 取得输出流
response.reset();// 清空输出流
System.out.println(fileName);
response.setHeader("Content-disposition", "attachment; filename="+URLEncoder.encode(fileName,"UTF-8")+".pdf");// 设定输出文件头
response.setContentType("application/pdf");// 定义输出类型
ITextRenderer renderer=new ITextRenderer();
ITextFontResolver fontResolver=renderer.getFontResolver();
//设置中文字体路径 中文支持这块我也没整太明白 我看网上说的是支持中文 就要在这里添加中文字体且网页上//也要加上css font引用添加的这个字体 但是我没在网页上引用这个添加的字体也显示中文了
fontResolver.addFont("C:/Windows/Fonts/simsunb.ttf",BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);
fontResolver.addFont("C:/Windows/Fonts/arial.ttf",BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);
String content =mergeMessage(template,map);
//传入最终的包含css的html代码给flying sauser 去解析啦
renderer.setDocumentFromString(content);
//设置图片的基础路径
renderer.getSharedContext().setBaseURL("file:/D:/apache-tomcat-7.0.68-windows-x64/apache-tomcat-7.0.68/webapps/report/styles/");
//支持BASE64图片
renderer.getSharedContext().setReplacedElementFactory(new B64ImgReplacedElementFactory());
renderer.layout();
renderer.createPDF(os);
os.close();
}catch (Exception ex) {
ex.printStackTrace();
result.setSuccess(false);
result.setResultInfo(ex.getMessage());
}
}
<beans default-autowire="byName">
<bean id="exportPDFHelper" class="com.takungae.report.common.utils.ExportPDFHelper">
<property name="exportPDFVelocityEngine" ref="exportPDFVelocityEngine"></property>
</bean>
<bean id="exportPDFVelocityEngine"
class="org.springframework.ui.velocity.VelocityEngineFactoryBean">
<property name="resourceLoaderPath" value="/WEB-INF/pdf-template" />
<property name="velocityProperties">
<props>
<prop key="input.encoding">GB18030</prop>
<prop key="output.encoding">UTF-8</prop>
</props>
</property>
</bean>
</beans>
导出为pdf示例图
感谢以下几篇文章的指引
(http://blog.csdn.net/hybaym/article/details/52999702)
(http://blog.sina.com.cn/s/blog_816730ea010hxxb.html)
(http://blog.csdn.net/woshizhangliang999/article/details/45197877)
(http://blog.csdn.net/jasonchris/article/details/7705631)
(http://adminjun.iteye.com/blog/2274861)