无法添加带附件注释的fdf

时间:2016-05-11 11:22:17

标签: annotations itext attachment fdf

我在一个应用程序上将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有一个带有类型附件文件的注释。

线程中的异常" main" com.itextpdf.text.exceptions.InvalidPdfException:在文件指针处读取字符串时出错5106590     at com.itextpdf.text.pdf.PRTokeniser.throwError(PRTokeniser.java:220)     at com.itextpdf.text.pdf.PRTokeniser.nextToken(PRTokeniser.java:411)     at com.itextpdf.text.pdf.PRTokeniser.nextValidToken(PRTokeniser.java:282)     at com.itextpdf.text.pdf.PdfReader.readPRObject(PdfReader.java:1908)     at com.itextpdf.text.pdf.PdfReader.readArray(PdfReader.java:1891)     at com.itextpdf.text.pdf.PdfReader.readPRObject(PdfReader.java:1946)     at com.itextpdf.text.pdf.PdfReader.readDictionary(PdfReader.java:1877)     at com.itextpdf.text.pdf.PdfReader.readPRObject(PdfReader.java:1913)     at com.itextpdf.text.pdf.PdfReader.readDocObj(PdfReader.java:1411)     at 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版本

提前感谢您的回复

此致

法比安

1 个答案:

答案 0 :(得分: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对象&#34;不要与真实的碰撞,只需从FdfReader派生一个类并覆盖方法readPRObject(),如下所示:

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

ImprovedFdfReader.java

使用正常testReadFdfFabienLevalois的{​​{3}}测试方法FdfReader阅读提供的FDF itext-SO.fdf时失败,请使用测试方法testReadFdfFabienLevaloisImproved执行此操作ImprovedFdfReader成功。