如果页面大小不同,如何将外部pdf文档中的页面添加到目标pdf?这是我想要完成的事情:

我尝试使用LayerUtility(就像在这个例子中PDFBox LayerUtility - 将图层导入到现有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();
Run Code Online (Sandbox Code Playgroud)
我做错了什么?
主要问题是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 ...
Run Code Online (Sandbox Code Playgroud)
事实证明,OP的设置中缺少fontbox.jar.
此处描述了 PDFBox版本1.8.x依赖项.特别是有三个核心组件pdfbox,fontbox和jempbox,所有这些组件都应存在于同一版本中,并且存在所需的依赖性commons-logging.
一旦添加了缺失的组件,样本就能正常工作.
可以通过AffineTransform参数中的转换将导入的页面定位在目标页面上.此参数还允许其他变换,例如缩放,旋转,镜像,倾斜,......*
对于原始样本文件,此PDF页面

被添加到此页面上

这导致了这个页面

OP然后想知道
如何定位导入的图层
layerUtility.appendFormAsLayer呼叫中的参数是AffineTransform affineTransform.new AffineTransform()这里使用的OP 创建了一个单位矩阵,这又使得源页面被添加到坐标系的原点,在这种情况下是在底部.
通过使用翻译而不是身份,例如
PDRectangle destCrop = destinationPages.get(0).findCropBox();
PDRectangle sourceBox = firstForm.getBBox();
AffineTransform affineTransform = AffineTransform.getTranslateInstance(0, destCrop.getUpperRightY() - sourceBox.getHeight());
Run Code Online (Sandbox Code Playgroud)
可以将源页面放在其他位置,例如在顶部:

不幸的是,事实证明,layerUtility.appendFormAsLayer将表单附加到页面而不重置图形上下文.
layerUtility.appendFormAsLayer 使用此代码添加其他内容流:
PDPageContentStream contentStream = new PDPageContentStream(
targetDoc, targetPage, true, !DEBUG);
Run Code Online (Sandbox Code Playgroud)
遗憾的是,此构造函数生成的内容流将继承目标页面现有内容末尾的图形状态.这尤其意味着用户空间坐标系可能不再处于其默认状态.一些软件例如镜像坐标系以使y坐标向下增加.
如果相反
PDPageContentStream contentStream = new PDPageContentStream(
targetDoc, targetPage, true, !DEBUG, true);
Run Code Online (Sandbox Code Playgroud)
如果已经使用过,图形状态将被重置为默认状态,因此可以知道.
因此,该方法本身不能以受控方式用于任意输入.
幸运的是,LayerUtility还有一种方法wrapInSaveRestore(PDPage)可以通过操纵给定页面的内容来最终获得默认图形状态来克服这个弱点.
因此,人们应该取而代之
layerUtility.appendFormAsLayer(destinationPages.get(0), firstForm, affineTransform, "external page");
Run Code Online (Sandbox Code Playgroud)
通过
PDPage destPage = destinationPages.get(0);
layerUtility.wrapInSaveRestore(destPage);
layerUtility.appendFormAsLayer(destPage, firstForm, affineTransform, "external page");
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2058 次 |
| 最近记录: |