在使用itext编辑pdf时获得异常

时间:2017-04-04 15:22:19

标签: java pdf itext ecm redaction

我在尝试使用itext编辑pdf文档时遇到异常。 这个问题非常零星,有时它正在发挥作用,有时它会引发错误。

at com.itextpdf.text.pdf.parser.PdfContentStreamProcessor.access$6100(PdfContentStreamProcessor.java:60)
at com.itextpdf.text.pdf.parser.PdfContentStreamProcessor$Do.invoke(PdfContentStreamProcessor.java:991)
at com.itextpdf.text.pdf.pdfcleanup.PdfCleanUpContentOperator.invoke(PdfCleanUpContentOperator.java:140)
at com.itextpdf.text.pdf.parser.PdfContentStreamProcessor.invokeOperator(PdfContentStreamProcessor.java:286)
at com.itextpdf.text.pdf.parser.PdfContentStreamProcessor.processContent(PdfContentStreamProcessor.java:425)
at com.itextpdf.text.pdf.pdfcleanup.PdfCleanUpProcessor.cleanUpPage(PdfCleanUpProcessor.java:160)
at com.itextpdf.text.pdf.pdfcleanup.PdfCleanUpProcessor.cleanUp(PdfCleanUpProcessor.java:135)
at RedactionClass.tgestRedactJavishsInput(RedactionClass.java:56)
at RedactionClass.main(RedactionClass.java:23)

我用来编辑的代码如下:

public static void testRedact() throws IOException, DocumentException {

    InputStream resource = new FileInputStream("D:/itext/edited_120192824_5 (1).pdf");
    OutputStream result = new FileOutputStream(new File(OUTPUTDIR,
            "aviteshs.pdf"));

    PdfReader reader = new PdfReader(resource);
    PdfStamper stamper = new PdfStamper(reader, result);
    int pageCount = reader.getNumberOfPages();
    Rectangle linkLocation1 = new Rectangle(440f, 700f, 470f, 710f);
    Rectangle linkLocation2 = new Rectangle(308f, 205f, 338f, 215f);
    Rectangle linkLocation3 = new Rectangle(90f, 155f, 130f, 165f);
    List<PdfCleanUpLocation> cleanUpLocations = new ArrayList<PdfCleanUpLocation>();
    for (int currentPage = 1; currentPage <= pageCount; currentPage++) {
        if (currentPage == 1) {
            cleanUpLocations.add(new PdfCleanUpLocation(currentPage,
                    linkLocation1, BaseColor.BLACK));
            cleanUpLocations.add(new PdfCleanUpLocation(currentPage,
                    linkLocation2, BaseColor.BLACK));
            cleanUpLocations.add(new PdfCleanUpLocation(currentPage,
                    linkLocation3, BaseColor.BLACK));
        } else {
            cleanUpLocations.add(new PdfCleanUpLocation(currentPage,
                    linkLocation1, BaseColor.BLACK));
        }
    }
    PdfCleanUpProcessor cleaner = new PdfCleanUpProcessor(cleanUpLocations,
            stamper);
    try {
        cleaner.cleanUp();
    } catch (Exception e) {
        e.printStackTrace();
    }
    stamper.close();
    reader.close();

}

由于客户文档我无法共享,因此尝试查找相同的测试数据。

请在此处找到该文档:

https://drive.google.com/file/d/0B-zalNTEeIOwM1JJVWctcW8ydU0/view?usp=drivesdk

1 个答案:

答案 0 :(得分:0)

简而言之: NullPointerException的原因是iText不支持从显示的页面中获取XObject资源继承。根据PDF规范这个构造已经过时了但是它可以在遵循早期PDF引用而不是规范的PDF中遇到。

原因

相关文档的第1页包含4个名为 I1 的XObject资源, M0 P1 Q0

RUPS screenshot

正如您在屏幕截图中看到的, Q0 特别没有自己的资源字典。但它的最后指示是

q
413 0 0 125 75 3086 cm
/I1 Do
Q

Id est引用资源 I1

现在,在形式XObjects的情况下,iText假定其内容引用的资源包含在他们自己的资源字典中。

结果:iText访问null字典并发生NullPointerException

规范

PDF规范ISO 32000-1规定:

  

资源字典应通过以下方式之一与内容流相关联:

     
      
  • 对于作为页面内容条目值的内容流(或者是作为该条目值的数组元素),资源字典应由页面字典的资源或是继承的,如7.7.3.4,&#34;页面属性的继承,&#34;来自页面对象的某个祖先节点。

  •   
  • 对于其他内容流,符合规范的编写者应在流的字典中包含资源条目,指定包含该内容流使用的所有资源的资源字典。这适用于定义表单XObject,模式,Type 3字体和注释的内容流。

  •   
  • 遵循早期版本的PDF编写的PDF文件可能省略了页面上使用的所有表单XObjects和Type 3字体中的 Resources 条目。从这些表单和字体引用的所有资源都应从使用它们的页面的资源字典继承。此构造已过时,不应由符合规范的作者使用。

  •   

(ISO 32000-1,第7.8.3节 - 资源词典)

因此,在手头的情况下,我们处于过时选项3的情况, Q0 引用页面 I1 > Q0 用于。

相关文档的版本标题声称符合PDF 1.5一致性(与PDF规范的PDF 1.7相反)。那么让我们看一下PDF Reference 1.5。那里对应于选项三的段落是:

  
      
  • 表单XObject或Type 3字体的字形描述可能省略资源   输入,在这种情况下,资源将在。的资源条目中查找   使用表单或字体的页面。 不推荐这种做法。
  •   

因此,总结一下,有问题的PDF使用了PDF规范(2008年发布,使用了9年!)的构造过时,甚至PDF文件声称符合推荐的PDF参考。另一方面,iText不支持这种过时的结构。

想法如何解决这个问题

基本上,PDF清理代码必须扩展到

  • 请记住PdfCleanUpProcessor
  • 中当前页面的资源
  • 使用PdfCleanUpContentOperator方法invoke中的这些当前页面资源,以防执行运算符引用没有自己资源的表单XObject。

不幸的是,invoke中使用的某些成员是私有的。因此,必须复制PdfCleanUp代码或者反复使用。

(iText 5.5.12-SNAPSHOT)

iText 7

iText 7 PDF CleanUp工具也会遇到PDF问题,IllegalStateException声明"Graphics state is always deleted after event dispatching. If you want to preserve it in renderer info, use preserveGraphicsState method after receiving renderer info."

的例外情况除外

由于在事件调度期间抛出此异常,因此此错误消息没有意义。不幸的是,PDF CleanUp工具已经成为iText 7中的封闭源代码,所以要解决这个问题并不容易。

(iText 7.0.3-SNAPSHOT; PDF CleanUp 1.0.2-SNAPSHOT)