itextpdf拼接多份文件一定要按照PdfCopy->Document->OutputStream的顺序关闭

原始需求:审批表只能单份打印,新增审批表批量打印功能

现状:前同事已离职,代码改了一版。接到需求后,先看代码目前的功能,发现是参考了其他服务中的批量打印,且能打印,但是有个问题,就是打印出来的审批表没有签章。于是查看源码,发现是jsp页面上直接调用了润乾的com.runqian.report4.view.applet.DirectPrintWithoutSHow,而其继承了DirectPrintApplet,直接通过报表名称、查询参数、打印参数等,输出pdf并打印。没有签章。继续查看单份打印源码,发现是通过runqian提供的api,获取到pdf之后,再从数据库中查询签章图片的base64,使用itextpdf将签章图片添加到pdf的指定位置。也就是说,项目使用版本的润乾报表本身未提供签章功能。

思路:参考单份打印功能,开发批量打印功能,接口接收多个报表的名称以及查询参数,使用上述提到的方法添加签章图片,并将每个pdf都转成byte数组,最后使用itextpdf拼接成完整pdf。

遇到的坑:拼接过程会使用到itextpdf包下的DOcument和PdfCopy类,以及OutputStream用于response的返回流,在关闭资源时,一定要按照PdfCopy->Document->OutputStream的顺序关闭。原因是PdfCopy在调用close()方法时,才会把拼接完的pdf格式整理成完整格式,在close之前,pdf格式不正确,如果先调用OutputStream.close(),则会导致pdf流格式不正确,前端无法正确解析。出现这个问题是因为,项目中使用itextpdf版本较老,其中的类均没有实现AutoCloseable或者继承Closeable,导致无法使用try-with-resources语法自动关闭。于是我在开发时,只用try-with-resources管理了OutputStream,而DOcument和PdfCopy都是在finally块中手动关闭。然而这导致OutputStream在DOcument和PdfCopy之前关闭,进而导致pdf流格式不正确,前端无法正确解析。

posted @ 2026-01-04 14:07  解忧杂货铺12138  阅读(4)  评论(0)    收藏  举报