最近项目中遇到这样一个场景:服务器上有上百页的html网页需要打印成纸质文档。
通常的网页打印很简单,调用一下window.print()就能够选择打印机打印了。可是现在这个网页数量太多了,不能够在浏览器中全部打开。于是乎开始在网上搜索开始了,看看有没有什么现成的程序能用。很可惜没有直接的解决方案,只有大致的思路:
(1)、先在服务器上把这些网页一起转换成一个pdf文档,然后再返回到浏览器中,让用户使用pdf的打印功能。然而有一个问题,这上百个网页转成pdf需要很长的时间,会需要等待一段时间后才能打印。
(2)、第二种和第一种其实差不多,需要在客户电脑上启动一个客户端,这个客户端把需要打印的网页一个一个下载下来,转为pdf,再打印。每个网页需要依次进行处理。(至于为什么转换成pdf,网页如果直接发送到打印机中,打出来的就是html标签了,需要渲染之后才能打印出看到的效果)。

思路有了,之后就开始动手码程序了。
开始:客户启动客户端代理,这是一个websocket服务,使用netty-socket 作为服务端,客户端使用socket.io提供的js连接代理程序。
第一步:发送打印任务。浏览器将任务发送给代理程序。
var task = {printerName: printerName,//打印机名称
taskName: '打印测试',
requestUrls: [
{
url: 'http://www.baidu.com',
parameters: [{name: 'itemInstIds', value: '1262'}]
}, {
url: 'http://www.baidu.com',
parameters: [{name: 'itemInstIds', value: '1261'}]
},
],
cookie: {
name: 'JSESSIONID',
value: '1111',
cookieDomain: 'ip',
cookiePath: '/'
}
};
socket.emit('newTask', task);
第二步、客户端代理监听newTask事件后,使用httpclient下载网页。
第三步、客户端代理将下载的网页转为pdf文件。这里使用了wkhtmltopdf。之前使用的是itext转换,对于简单的网页转换效果还不错。然而项目中的每个html都十分复杂,只有这个webkit渲染引擎效果不错。使用参考:How to convert an HTML file to PDF using wkhtmlpdf in Java。
第四步、使用java将读取生成的pdf,发送到打印机。这里使用pdfbox读取文件并打印。
//获取打印机
PrinterJob printerJob = PrinterJob.getPrinterJob();
PrintService selectedPrintService = getPrintServiceByName(printerName);
printerJob.setPrintService(selectedPrintService);
//加载pdf文件
PDDocument doc = PDDocument.load(new File(pdfFile));
PDFPageable document = new PDFPageable(doc);
printerJob.setPageable(document);
//打印
printerJob.print();
doc.close();
第五步、将打印结果使用websocket推送到客户浏览器端。
整个程序看上去和简单,使用各种开源程序组装而来。但又很多细节问题需要处理,如果多个网页中有一个打印失败了怎么办,打印是不是需要实时的更新打印进度到浏览器,这几个步骤中是不是有可以并行的。
最后还要把整个程序打包成一个exe安装包。
整体思路参考了:
浙公网安备 33010602011771号