前言
最近在一个接的私活中,甲方提出一个点击按钮,浏览器显示评价详情报表并打印的需求。这个需求乍一听的时候有点懵,不知从何下手,如何导出?如何适配多种报表格式、如何让浏览器打印?
经过一整子的资料收集,理清了技术的可行性以及所要使用的相关框架,下面先来看下最终实现的效果~
即PDF的每一页都是上图的模样,同时刚刚进入该页面时会打开浏览器的打印功能,例如下图的样子,功能的实现主要工作量都在后台完成,这就是我们最终实现的效果
技术栈
名称 |
版本 |
SpringBoot |
2.4.5 |
poi-tl |
1.12.1 |
aspose-words |
15.8 |
思路
生成PDF
可以看到上图的内容是一个表格数据,因此我们先考虑如何生成动态表格,可以通过poi-tl框架来实现表格的生成,具体的使用可以看之前写的水文
通过继承DynamicTableRenderPolicy
类来实现复杂word表格的实现,该类的使用可以去框架官网查看,这里就不复制了。
当word文档生成成功后,就会发现这只是一个docx的文档,因此我们需要将其转换为PDF的类型,为此我们需要一个能够将word文档转换为PDF的框架。
网上大致有两种推荐
- fr.opensagres.poi.xwpf.converter.pdf
- aspose-words
先说fr.opensagres.poi.xwpf.converter.pdf
框架,自己实测Word文档转换为PDF格式会出现错位,表格布局尤其明显,但他的使用十分简单,只需要引入Jar包便可以使用。
1 2 3
| String wordPath ="demo.docx"; String pdfPath = "demo.pdf"; PdfConverter.getInstance().convert(new XWPFDocument(FileUtil.getInputStream(wordPath)), FileUtil.getOutputStream(pdfPath), PdfOptions.create());
|
如果不在意转换后错位的问题,或者内容只有纯文本等可以考虑使用该框架。
说回本需求,由于甲方不能接受PDF不美观的问题,因此我们需要使用另一种框架aspose-words
。
aspose-words
是需要购买的,但他提供了很好的无损转换效果,因此我们需要使用一些手段来获得,这些网上有很多资源提供。当我们引入jar包执行对应的转换方法后,就会发现几乎无损的转换为PDF了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| @Slf4j public class PdfUtils {
private static boolean getLicense() { boolean result = false; try { InputStream inputStream = PdfUtils.class.getClassLoader().getResourceAsStream("license.xml"); License license = new License(); license.setLicense(inputStream); result = true; } catch (Exception e) { throw new OperateException("获得license文件出错:{}", ExceptionUtil.stacktraceToString(e)); } return result; }
public static void doc2pdf(String wordPath, String pdfPath) { // 验证License 若不验证则转化出的pdf文档会有水印产生 if (BooleanUtil.isFalse(getLicense())) { return; } File file = new File(pdfPath); try (FileOutputStream fileOutputStream = new FileOutputStream(file)) { long old = System.currentTimeMillis(); Document doc = new Document(wordPath); doc.save(fileOutputStream, SaveFormat.PDF); long now = System.currentTimeMillis(); log.info("{}转换为{}共耗时{}秒", wordPath, pdfPath, ((now - old) / 1000.0)); } catch (Exception e) { throw new OperateException("转换{}为{}时出错:{}", wordPath, pdfPath, ExceptionUtil.stacktraceToString(e)); } } }
|
open+print实现打印
当我们成功将word文档转换为PDF后,就可以开始前端打印的工作了,JavaScript提供了window.print()
方法来调用浏览器的打印功能,因此就很简单啦。
前端核心代码如下,后台返回对应PDF的链接,浏览器通过open
方法在新页面打开,随后等待其加载完后调用print
方法。
1 2 3 4
| const pdfWindow = window.open(baseUrl+response) pdfWindow.window.onload = function(){ pdfWindow.window.print() }
|