问题描述
我们正在尝试实现Apache PDFBox覆盖。效果很好,但是重叠页面上的超链接会丢失。
在我们的案例中,客户上传了一个覆盖层,上面包含经常可点击的详细信息,例如网站和电子邮件地址。前景PDF是发票,还可以包含例如指向产品页面的超链接。
基本上这是我们的代码:
Overlay overlay = new Overlay(); //org.apache.pdfBox.multipdf.Overlay
overlay.setInputPDF(inputDoc); //PDDDocument inputDoc with hyperlinks
overlay.setDefaultOverlayPDF(overlayDoc); //PDDDocument overlayDoc with hyperlinks
inputDoc上的超链接仍然有效,但是overlayDoc上的超链接无效。还有另一种方法(使用PDFBox)将覆盖的PDF标记到inputDoc上,同时保持诸如超链接的交互吗?
[更新]:可能的解决方法,发布在下面。
解决方法
解决方案
这是一个难题,令人惊讶的是,关于此问题的信息很少。但是,最终它非常简单,我设法使其正常工作。
基本上我所做的是(下面的代码示例):
- 从叠加层PDF中获取getAnnotations
- 使用PDFBox叠加层将输入文档与叠加层PDF叠加
- 保存新的重叠文档
- 遍历新文档页面:PDDocument.getPages()
- 对于新文档中的每个页面,请添加覆盖PDF中的注释
- 就这些
似乎工作得很好。我唯一不确定的是在下面的代码中执行annot.setPage(p)的部分。因为每次都使用相同的注释,所以我在新文档中设置了不同的页面。它可以工作,但是我认为创建一个新的注释实例并将新的注释添加到文档中会更清洁。但是,我还没有弄清楚如何将注释克隆到新实例中。欢迎对此发表意见:)
这是我的代码(有一点被剥夺)供有兴趣的人使用:
//instantiate PDDocuments for input PDF and overlay PDF
PDDocument PDDDoc_inputDoc = PDDocument.load(...);
PDDocument PDDDoc_overlay = PDDocument.load(...);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
//create PDFBox overlay
Overlay overlay = new Overlay();
overlay.setOverlayPosition(Overlay.Position.BACKGROUND);
//set inputDoc and overlayDoc PDFs
overlay.setInputPDF(PDDDoc_inputDoc);
overlay.setDefaultOverlayPDF(PDDDoc_overlay);
//execute overlay function
overlay.overlay(new HashMap<>()).save(baos);
//create new PDDocument from overlay
PDDocument PDD_newOverlaydDocument = PDDocument.load(new ByteArrayInputStream(baos.toByteArray()));
//for every page in the new (overlayed) document,add annotation from the source overlay PDF to the new PDF
PDPageTree pages = PDD_newOverlaydDocument.getPages();
for(PDPage p : pages){
//get annotations from new document page
List<PDAnnotation> pageAnnotations = p.getAnnotations();
//add annotations from overlay page to the page
for(PDAnnotation annot : overlayAnnotations) {
annot.setPage(p);
pageAnnotations.add(annot);
}
}
//save new PDDDocument to outputstream or file and dow whatever you want with it
PDD_newOverlaydDocument.save(...);
//close streams,cleanup,etc
....