如果页面大小不同,如何将外部pdf文档中的页面添加到目标pdf? 这是我想要完成的事情:
我尝试使用LayerUtility(就像在此示例PDFBox LayerUtility - Importing layers into existing PDF中一样),但是一旦我从外部pdf导入页面,该过程就会挂起:
PDDocument destinationPdfDoc = PDDocument.load(fileInputStream);
PDDocument externalPdf = PDDocument.load(EXTERNAL PDF);
List<PDPage> destinationPages = destinationPdfDoc.getDocumentCatalog().getAllPages();
LayerUtility layerUtility = new LayerUtility(destinationPdfDoc);
// process hangs here
PDXObjectForm firstForm = layerUtility.importPageAsForm(externalPdf, 0);
AffineTransform affineTransform = new AffineTransform();
layerUtility.appendFormAsLayer(destinationPages.get(0), firstForm, affineTransform, "external page");
destinationPdfDoc.save(resultTempFile);
destinationPdfDoc.close();
externalPdf.close();
我做错了什么?
答案 0 :(得分:5)
主要问题是PDFBox有三个核心组件,一个需要依赖。缺少一个核心组件。
在评论中,OP澄清了
实际上,进程没有挂起,根本就没有创建文件。
由于这听起来可能有异常或错误,因此在聊天中提议尝试将代码封装为try { ... } catch (Throwable t) { t.printStackTrace(); }
块。事实上,
java.lang.NoClassDefFoundError: org/apache/fontbox/util/BoundingBox
at org.apache.pdfbox.util.LayerUtility.importPageAsForm(LayerUtility.java:203)
at org.apache.pdfbox.util.LayerUtility.importPageAsForm(LayerUtility.java:135)
at ...
事实证明,OP的设置中缺少fontbox.jar。
PDFBox版本1.8.x依赖项描述为here。特别是有三个核心组件 pdfbox , fontbox 和 jempbox 所有这些组件都应存在于同一版本中,并且需要依赖 commons-logging 。
一旦添加了缺失的组件,样本就能正常工作。
导入的页面可以通过AffineTransform
参数中的翻译定位在目标页面上。该参数还允许其他变换,例如,缩放,旋转,镜像,倾斜,...... *
对于原始样本文件此PDF页面
已添加到此页面
导致了这个页面
OP然后想知道
如何定位导入的图层
layerUtility.appendFormAsLayer
来电中的参数是AffineTransform affineTransform
。 OP在这里使用了new AffineTransform()
,它创建了一个单位矩阵,这又使得源页面被添加到坐标系的原点,在这种情况下是在底部。
使用翻译而不是身份,例如
PDRectangle destCrop = destinationPages.get(0).findCropBox();
PDRectangle sourceBox = firstForm.getBBox();
AffineTransform affineTransform = AffineTransform.getTranslateInstance(0, destCrop.getUpperRightY() - sourceBox.getHeight());
可以将源页面放在别处,例如在顶部:
不幸的是,layerUtility.appendFormAsLayer
将表单附加到页面而不重置图形上下文。
layerUtility.appendFormAsLayer
使用此代码添加其他内容流:
PDPageContentStream contentStream = new PDPageContentStream(
targetDoc, targetPage, true, !DEBUG);
不幸的是,此构造函数生成的内容流将继承目标页面现有内容末尾的图形状态。这尤其意味着用户空间坐标系可能不再处于其默认状态。一些软件例如镜像坐标系使y坐标向下增加。
如果是
PDPageContentStream contentStream = new PDPageContentStream(
targetDoc, targetPage, true, !DEBUG, true);
已被使用,图形状态将被重置为其默认状态,因此可以知道。
因此,就其自身而言,这种方法不能以受控方式用于任意输入。幸运的是,LayerUtility
还有一个方法wrapInSaveRestore(PDPage)
来通过操纵给定页面的内容来克服这个弱点,使其在最后具有默认的图形状态。
因此,应该替换
layerUtility.appendFormAsLayer(destinationPages.get(0), firstForm, affineTransform, "external page");
通过
PDPage destPage = destinationPages.get(0);
layerUtility.wrapInSaveRestore(destPage);
layerUtility.appendFormAsLayer(destPage, firstForm, affineTransform, "external page");