前言
以前公司用Lodop打印控件,安装在Chrome浏览器。新版的谷歌浏览器已经不再支持安装本地插件了。基本上所有Lodop以及其他类似打印控件的使用者无不诟病其使用变态。后来使用JasperReport做报表,WEB应用可以直接生成HTML,PDF等。本地打印还可以指定打印机。JasperReport支持分组,子报表等;可以设计出很多复杂的报表。简直是一个良心大作。
但是有时候我们打印需要指定打印机,在网页端不好实现了。需要在客户机安装一个打印中间件,提供打印数据,并让它实现个性化打印。接下来我们实现这个中间件:
演示
流程图
系统的复杂点在于** 网页 发送打印数据给 本地打印程序 **。思路如下:
本地打印程序(以下称ClientPrinter),java实现的c/s程序。负责接收服务端的打印数据,并且实现打印。
用户在网页点击打印时,服务器返回jasper的模板文件和打印数据①
,然后JS跨域发送模板文件和打印数据到ClientPrinter,ClientPrinter将模板文件和打印数据处理生成报表,最后返回结果给** 网页 **。
用户在网页点击打印时,服务器生成JasperPrint对象流数据data,并且将data存入缓存;然后把对应的key返回到网页端(更好的办法是生成唯一url返回到网页);接着网页端通过自定义协议Url Protocol 调用本地的打印程序,本地程序通过url从服务端获取打印数据,最终完成打印。
*自定义协议Url Protocol请查看我另一篇博客 自定义Protocol URL从浏览器运行本地应用
服务端系统
服务端需要提供JasperPrint打印数据。这里服务端直接提供JasperReport Studio 报表设计工具可以点击这里下载。
//服务端网页js
function print(url){
location.href='albertprint://'+url;
}
上面js中的url表示唯一的一个链接,这个链接返回JasperPrint对象流数据。
客户端打印
public void print(String httpUrl) throws Exception{
Object en = HttpRequestUtil.request(httpUrl);//用上文提供的url从服务端获取打印对象流
ResponseEntity re = (ResponseEntity) en;
if(re.getStatus()==-1)throw new Exception(re.getMsg());
printService.print((JasperPrint)re.getObj());//打印
}
最近有点忙,过几天把PrintClient加入jre打包成exe安装包,客户机可以设置开机启动或者加入到服务
用户端DEMO: PrintClient https://github.com/zyqwst/PrintClient