-1

我在一个应用程序上工作,将注释从 fdf 文件添加到 Pdf 文件使用 iText 可以这样做

FdfReader aFdfReader = new FdfReader(new FileInputStream(args[0]));
PdfReader aReader = new PdfReader(new FileInputStream(args[1]));
PdfStamper aStamper = new PdfStamper(aReader, new FileOutputStream(args[2]));
aStamper.addComments(aFdfReader);
aStamper.close();

但是当我加载 fdf 时,我有这个异常。fdf 有一个带有类型附件文件的注释。

线程“主”com.itextpdf.text.exceptions.InvalidPdfException 中的异常:在 com.itextpdf.text.pdf.PRTokeniser.throwError(PRTokeniser.java:220) 在 com.itextpdf.text.pdf 的文件指针 5106590 处读取字符串时出错.PRTokeniser.nextToken(PRTokeniser.java:411) 在 com.itextpdf.text.pdf.PRTokeniser.nextValidToken(PRTokeniser.java:282) 在 com.itextpdf.text.pdf.PdfReader.readPRObject(PdfReader.java:1908) 在com.itextpdf.text.pdf.PdfReader.readArray(PdfReader.java:1891) 在 com.itextpdf.text.pdf.PdfReader.readPRObject(PdfReader.java:1946) 在 com.itextpdf.text.pdf.PdfReader.readDictionary( PdfReader.java:1877) 在 com.itextpdf.text.pdf.PdfReader.readPRObject(PdfReader.java:1913) 在 com.itextpdf.text.pdf.PdfReader.readDocObj(PdfReader.java:1411) 在 com.itextpdf.text .pdf.FdfReader.readPdf(FdfReader.java:105) 在 com.itextpdf.text.pdf.PdfReader.(PdfReader.java:181) 在 com.itextpdf.text.pdf.PdfReader.(PdfReader.java:395) 在 com.itextpdf.text.pdf.PdfReader.( PdfReader.java:415) 在 com.itextpdf.text.pdf.FdfReader.(FdfReader.java:92) 在 com.artesys.pdf.itext.pdf.AddFdf.main(AddFdf.java:18)

我使用 itext_so.pdf 进行测试以附加到注释

如果我用 helloword 进行测试,我工作正常

我用的是 5.5.9 版本

预先感谢您的回复

问候

法比安

4

1 回答 1

0

FDF 很特殊,因为它在流中包含 PDF;此 PDF 流是部分未压缩的;因此,PDF 语法,特别是 PDF 间接对象开始是可见的。

并且FdfReader工作不正确:它假定流内容中的这些间接对象的开始是顶级 FDF 对象开始并在尝试读取这些对象时失败。

可以通过使FdfReader对象读取更宽容来快速解决此问题。

FDF

您的 FDF 如下所示:

%FDF-1.2
%âãÏÓ
1 0 obj
<</FDF<</Annots[2 0 R]/F(http://localhost:8780/PachaServer/downloadpacha?pathpdf=Rendition.pdf&edit=false&loginname=fhfgh)/ID[<2175D5400E41761374A2EB01E7026C68><5E9C3BFFF121CE737ED66FF7318CA58D>]/UF(http://localhost:8780/PachaServer/downloadpacha?pathpdf=Rendition.pdf&edit=false&loginname=fhfgh)>>/Type/Catalog/Version/1.6>>
endobj
2 0 obj
<</C[0.25 0.333328 1.0]/Contents(itext_so.pdf)/CreationDate(D:20160519150439+02'00')/F 28/FS 3 0 R/M(D:20160519150439+02'00')/NM(79bcf116-d9bd-4ade-a8cd-7575351271fd)/Name/Paperclip/Page 0/RC(<?xml version="1.0"?><body xmlns="http://www.w3.org/1999/xhtml" xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/" xfa:APIVersion="Acrobat:15.16.0" xfa:spec="2.0.2" ><p>itext_so.pdf</p></body>)/Rect[183.106 684.663 190.106 701.663]/Subj(Pièce jointe)/Subtype/FileAttachment/T(Fabien.Levalois)/Type/Annot>>
endobj
3 0 obj
<</EF<</F 4 0 R>>/F(itext_so.pdf)/Type/Filespec/UF(itext_so.pdf)>>
endobj
4 0 obj
<</DL 10536008/Filter/FlateDecode/Length 10207532/Params<</CheckSum("}þ¶îô/Óý‡†d’ÒÎ)/CreationDate(D:20160511112202+02'00')/ModDate(D:20160511112205+02'00')/Size 10536008>>/Subtype/application#2Fpdf>>stream
... [10207532 data bytes] ...
endstream
endobj
trailer
<</Root 1 0 R>>
%%EOF

这个结构是正确的。但是大流的内容,对象 4 中的 10207532 个数据字节是特殊的:它们构成了一个 PDF 文档,并且由于该文档已经被压缩,当嵌入 FDF 和原始 PDF 语法时,它部分无法进一步压缩变得分段可见,例如流中的一些 660000 字节突然出现表示当前 PDF 流的结束和另一个间接 PDF 对象的开始的字节序列:

endstream
endobj
10283 0 obj
<</Extends 10282 0 R/Filter/FlateDecode/First 1139/Length 4195/N 100/Type/ObjStm>>stream
...
endstream
endobj
10284 0 obj
<</Extends 10282 0 R/Filter/FlateDecode/First 1139/Length 4018/N 100/Type/ObjStm>>stream
...
endstream
endobj
10285 0 obj
<</Extends 10282 0 R/Filter/FlateDecode/First 190/Length 1001/N 18/Type/ObjStm>>stream

等等等等等等

但是,由于这些 PDF 对象仅是分段可见的,因此尝试按原样读取它们可能会导致错误。

FdfReader

由于 FDF 不需要包含交叉引用部分,因此FdfReader第一步尝试通过在文件中搜索似乎是间接对象开始的字节序列并从中派生交叉引用部分来创建一个。

但是,这是不正确的,因为在 FDF 之类的情况下,它会创建许多错误的交叉引用条目,并且在读取这些错误的间接对象时,除非错误的对象在语法上是正确的,否则会发生错误。

对于您的 PDF,许多错误对象在语法上都是正确的,直到在错误间接对象被部分重新压缩的异常中提到的偏移 5106590 附近的位置。并且在尝试阅读时,FdfReader会引发您观察到的异常。

但问题不仅在于这样的语法错误(毕竟这些可以被捕获和忽略),而且虚假对象和真实对象可能具有相同的对象编号。因此,FdfReader可能会使用虚假对象而不是真实对象!

快速修复

虽然基本上必须重新实现交叉引用重建代码才能FdfReader真正修复,但有一个快速修复它允许它正确处理“虚假 FDF 对象”不与真实对象碰撞的 FDF,只需导出一个类,FdfReader并覆盖这样的方法readPRObject()

@Override
protected PdfObject readPRObject() throws IOException
{
    try
    {
        return super.readPRObject();
    }
    catch (InvalidPdfException e)
    {
        return PdfNull.PDFNULL;
    }
}

(改进的FdfReader.java )

使用ReadFdf.java测试方法读取提供的 FDF itext-SO.fdf时正常失败,使用测试方法执行此操作成功。testReadFdfFabienLevaloisFdfReadertestReadFdfFabienLevaloisImprovedImprovedFdfReader

于 2016-05-20T16:01:20.063 回答