读取MS Office生成的PDF文件时出错

时间:2019-10-30 17:39:12

标签: pdf itext ms-office itext7

每当我尝试读取Office生成的PDF文件时,似乎都会出现错误:

com.itextpdf.kernel.PdfException: Append mode requires a document without errors, even if recovery is possible.
    at com.itextpdf.kernel.pdf.PdfDocument.open

有问题的文件示例:https://drive.google.com/open?id=1fnwtXfEGg6BIeVuAi-l28Ol_dxbCd12F和用于打开文件的代码片段。我的目标是做一个独立的签名,只要不是MS Office生成的文件,此签名就可以正常工作。

PdfReader reader = new PdfReader(docPath);
StampingProperties properties = new StampingProperties();
        properties.useAppendMode();

//This is where the error is thrown.
PdfSigner signer = new PdfSigner(reader, new FileOutputStream(outputPath), properties);

我已经阅读了与基本相同的问题: Append mode requires a document without errors, even if recovery is possible ,尝试了Lowagie关于删除字节的建议

xref
0 24
0000000000 65535 f 
0000011981 00000 n 
0000000239 00000 n 
0000003212 00000 n 
0000000022 00000 n 
0000000220 00000 n 
0000000343 00000 n 
0000003176 00000 n 
0000000000 00000 n 
0000003345 00000 n 
0000000440 00000 n 
0000003155 00000 n 
0000003295 00000 n 
0000003863 00000 n 
0000003519 00000 n 
0000003843 00000 n 
0000004099 00000 n 
0000011737 00000 n 
0000011758 00000 n 
0000011803 00000 n 
0000011877 00000 n 
0000011900 00000 n 
0000011942 00000 n 
0000011961 00000 n 
trailer
<< /Size 24 /Root 12 0 R /Info 1 0 R /ID [ <8e4b8658dd1d1f745bdf99a0eb05bb97>
<8e4b8658dd1d1f745bdf99a0eb05bb97> ] >>
startxref
12125
%%EOF

但是我的PDF抱怨并停止工作,还尝试离开%% EOF,但结果相同。

有两件事:

1)是否可以解决Lowagie和MKL讨论的错误?

2)解决此问题的方法可能是什么?

1 个答案:

答案 0 :(得分:1)

首先,question you refer to关于基本上相同的问题不是,您只会得到相同的错误消息。所讨论的PDF中有一个混合参考PDF,而您的文件不是:您的文件只有一个交叉参考表和一个预告片,而混合参考PDF具有(至少)两个交叉参考表,每个后跟一个预告片,以及后者的预告片具有 XRefStm 条目,该条目指向交叉引用流。混合参考PDF是有效的,iText 7曾经存在此类PDF问题,这是一个错误。

另一方面,您的PDF文件本身实际上有一个错误:交叉引用表声称对象8的文件偏移量为0

xref
0 24
...
0000000000 00000 n 

这不能成立,因为在文件的开头有PDF标头。而且,此后要到达的第一个对象是对象4,因此无法论证偏移之后的第一个对象是...

iText 7仅在源文件中未发现问题时才允许追加模式。这是合理的。

因此,如果您以可复制的方式得到该错误,则应向PDF生成器提交错误。

您声称​​ PDF文件由MS Office生成的。另一方面,PDF的元数据表明,虽然MS Word是文档的创建者,但实际的 PDF生成者是Quartz PDFContext。您可能要提交Quartz PDFContext问题。

一种变通方法是捕获此异常,然后在没有附加模式的情况下重试。

或者,如果您确实真的真的需要在附加模式下处理这些损坏的文件,则可以通过使用{}覆盖PdfReader来使hasRebuiltXref关于发现的错误始终返回false的方法,例如通过替换

PdfReader reader = new PdfReader(SOURCE);

作者

PdfReader reader = new PdfReader(SOURCE) {
    @Override
    public boolean hasRebuiltXref() {
        return false;
    }
};

StampNoChange测试testAppendTest

但是请注意,结果PDF仍然包含原始文件中标识的错误iText。因此,任何与PDF进行进一步处理的PDF处理器也可能会崩溃,要么与iText最初的方式相同,要么以其他某种可能很壮观的方式出现。