使用PDFBox LayerUtility导入页面为表单导致PDF文件大小翻倍
问题分析与解决
我有一个两页内容完全相同的PDF,使用Apache PDFBox的LayerUtility将每页导入为表单对象并生成新PDF后,输出文件大小直接翻倍了。
原因
你的代码里每次循环都会创建新的LayerUtility实例,并且重复导入相同的页面资源。因为原PDF两页的资源完全一致,但每次importPageAsForm都会把页面的资源(图片、字体等)复制到新文档里,两次导入就导致相同资源被存储了两次,最终文件大小翻倍。
解决方案
只需要导入一次表单对象,然后在两个新页面上重复绘制这个表单即可,这样资源只会被存储一次,文件大小就会和原文件相近。
修改后的代码:
import org.apache.pdfbox.Loader; import org.apache.pdfbox.io.RandomAccessReadBufferedFile; import org.apache.pdfbox.multipdf.LayerUtility; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.PDPageContentStream; import java.util.stream.IntStream; public class FormSample { public static void main (String[] args) { try { try (var inputDocument = Loader.loadPDF(new RandomAccessReadBufferedFile("test.pdf")); var outputDocument = new PDDocument()) { // 只导入一次表单对象(取第一页即可,因为两页内容相同) LayerUtility layerUtility = new LayerUtility(outputDocument); var form = layerUtility.importPageAsForm(inputDocument, inputDocument.getPage(0)); IntStream.range(0, inputDocument.getNumberOfPages()).forEach(pageIndex -> { try { var readPage = inputDocument.getPage(pageIndex); var newPage = new PDPage(readPage.getMediaBox()); outputDocument.addPage(newPage); try (var contentStream = new PDPageContentStream(outputDocument, newPage)) { contentStream.drawForm(form); } } catch (Exception e) { throw new RuntimeException(e); } }); outputDocument.save("form_test.pdf"); } } catch (Exception e) { throw new RuntimeException(e); } } }
额外优化
如果原PDF页数更多且存在重复页面,你还可以先缓存已导入的表单对象,避免重复导入相同内容的页面,进一步减少文件体积。
内容的提问来源于stack exchange,提问作者Kyle KYL
相关产品推荐
相关产品推荐

