扁平化并与PDFBox合并的文件正在共享常见的COSStream

时间:2017-11-06 15:21:09

标签: java pdf pdfbox

以下代码演示了一个非常奇怪的错误。一旦“源”文件关闭,“目标”文件无法保存和关闭,它将抛出“java.io.IOException:COSStream已关闭且无法读取。可能其封闭的PDDocument已关闭?”

如果我们注释掉保存源文件,那么目标将正确保存和关闭。这似乎清楚地表明源文件包含一个COSStream对象,该对象也存在于目标文件中。当我们关闭源文件然后无法保存目标时,源文件COSStream似乎已关闭。

如果我们注释掉展平源文件AcroForm,那么目标将正确保存和关闭。

这个简单的示例是尝试将表单的一个副本与其自身合并,如果您替换某些其他PDF文件(所有政府表单曾经是XFA文档),则错误将重现。大多数PDF都适用于这种情况。我们将XFA文档向下转换为普通PDF,以将其作为变量消除,并且错误仍然存​​在。

PDFBox 2.0.8及更早版本中存在问题

    @Test
    public void testMergeGovernmentForms() throws Exception {
    File file = new File("GeneralForbearance.pdf");
    PDDocument destination = PDDocument.load(file);

    PDDocument source = PDDocument.load(file);
    source.getDocumentCatalog().getAcroForm().flatten(); //comment out just this line and the destination.save will pass

    PDFMergerUtility appender = new PDFMergerUtility();

    appender.appendDocument(destination, source);

    source.close(); //comment out just this line and the destination.save will pass

    destination.save(File.createTempFile("PrintMergeIssue", ".pdf"));
    destination.close();

}

HERE

下载GeneralForbearance.pdf

此外,如果您“预先展平”政府表格并保存,您可以使用更简单的代码获得相同的行为。

    @Test
public void testMerge() throws Exception {
    PDFMergerUtility pdfMergerUtility = new PDFMergerUtility();
    PDDocument src = PDDocument.load(new File("C:/temp/GovFormPreFlattened.pdf"));
    PDDocument dest = PDDocument.load(new File("C:/temp/GovFormPreFlattened.pdf"));
    pdfMergerUtility.appendDocument(dest, src);
    src.close(); //if we don't close the src then we don't have an error
    dest.save(File.createTempFile("MergeIssue",".PDF"));
    dest.close();
}

可以找到预先扁平的政府表格HERE

1 个答案:

答案 0 :(得分:0)

PDFMergerUtility合并标记文档中存在一些问题,我将其修复,修补并作为问题PDFBOX-3999提交回Apache,如果需要,可以从那里下载补丁。此修补程序适用于2.0.8版