【问题标题】:PDFbox loading large filesPDFbox加载大文件
【发布时间】:2014-04-08 19:07:20
【问题描述】:

我正在尝试使用 PDFBox 将 pdf 文件的第一页转换为图像。 当我加载一个大的 pdf 文件时,我得到一个异常。

代码:

    PDDocument doc;
    try {
        InputStream input  = new URL("http://www.jewishfederations.org/local_includes/downloads/39497.pdf").openStream();
        doc = PDDocument.load(input);
        PDPage firstPage = (PDPage) doc.getDocumentCatalog().getAllPages().get(0);
        BufferedImage image =firstPage.convertToImage();
        File outputfile = new File("image2.png");
        ImageIO.write(image, "png", outputfile);
        input.close();
        doc.close();

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

例外:

org.apache.pdfbox.pdfparser.BaseParser parseCOSStream
WARNING: Specified stream length 72435 is wrong. Fall back to reading stream until 'endstream'.
org.apache.pdfbox.exceptions.WrappedIOException: Could not push back 72435 bytes in order to reparse stream. Try increasing push back buffer using system property org.apache.pdfbox.baseParser.pushBackSize
    at org.apache.pdfbox.pdfparser.BaseParser.parseCOSStream(BaseParser.java:554)
    at org.apache.pdfbox.pdfparser.PDFParser.parseObject(PDFParser.java:605)
    at org.apache.pdfbox.pdfparser.PDFParser.parse(PDFParser.java:194)
    at org.apache.pdfbox.pdmodel.PDDocument.load(PDDocument.java:1219)
    at org.apache.pdfbox.pdmodel.PDDocument.load(PDDocument.java:1186)
    at Worker.main(Worker.java:27)
Caused by: java.io.IOException: Push back buffer is full
    at java.io.PushbackInputStream.unread(Unknown Source)
    at org.apache.pdfbox.io.PushBackInputStream.unread(PushBackInputStream.java:144)
    at org.apache.pdfbox.io.PushBackInputStream.unread(PushBackInputStream.java:133)
    at org.apache.pdfbox.pdfparser.BaseParser.parseCOSStream(BaseParser.java:550)
    ... 5 more

【问题讨论】:

  • 增加推回缓冲区大小时会发生什么?
  • 到目前为止我还没有找到怎么做。
  • 你自己的错误信息说:Try increasing push back buffer using system property org.apache.pdfbox.baseParser.pushBackSize
  • 我无法重现 1.8.5 版本的问题。它很快就会发布,但你也可以在这里获得它:repository.apache.org/content/groups/snapshots/org/apache/…

标签: java pdfbox


【解决方案1】:

在 2.0.* 版本中,像这样打开 PDF:

PDDocument doc = PDDocument.load(file, MemoryUsageSetting.setupTempFileOnly());

这会将缓冲内存使用设置为仅使用大小不受限制的临时文件(无主内存)。

祝你好运

【讨论】:

    【解决方案2】:

    1.8.* PDFBox 版本的替代解决方案是使用非顺序解析器。在这种情况下,代码不会是

    doc = PDDocument.load(input);
    

    但是

    doc = PDDocument.loadNonSeq(input, null);
    

    该解析器(将是即将到来的 2.0 版本中唯一的一个)独立于回推缓冲区的大小。

    【讨论】:

      【解决方案3】:

      我有一个类似的问题,我认为这与基于错误的大型 pdf 文件有关,但事实证明并非如此。原来是一个损坏的pdf文件。

      对于我们的用例,我们有一个 pdf 模板文件(我们以编程方式填充其表单值)作为我们项目中的资源,该资源已融入我们的战争。

      我看到的异常供参考:org.apache.pdfbox.exceptions.WrappedIOException: Could not push back 480478 bytes in order to reparse stream. Try increasing push back buffer using system property org.apache.pdfbox.baseParser.pushBackSize。我们添加了属性,然后再次运行,我们遇到了不同的问题。

      下一个堆栈跟踪指出“无法读取字体 TimesNewRoman,Bold 的嵌入式 TTF”。我们花了一段时间,但是在爆炸战争并试图在战争中打开pdf文件后,我们注意到它已损坏,但源中的pdf文件没有损坏,可以毫无问题地打开。

      问题的根本原因是我们在 pom 中为资源文件夹添加了“过滤”。我们这样做是为了在我们的健康检查页面中使用一些反射来获取一些值,但这损坏了 pdf 文件,我们从以下参考中发现:https://bitbucket.org/petermr/xhtml2stm/issues/12/pdf-files-are-being-corrupted-at-some

      以下是我们设置的过滤示例:

      <resources>
          <resource>
              <directory>src/main/resources</directory>
              <filtering>true</filtering>
          </resource>
      </resources>
      

      我们的解决方案是从我们的 pom 中删除它,并重新设计我们获取健康页面信息的方式。

      【讨论】:

        【解决方案4】:

        首先,找到当前缓冲区大小:

        System.out.println(System.getProperty("org.apache.pdfbox.baseParser.pushBackSize"));
        

        既然您有了基线,就按照它的建议去做。使用此命令将缓冲区大小增加到刚刚打印出来的大小:

        System.setProperty("org.apache.pdfbox.baseParser.pushBackSize", "<buffer size>");
        

        不断增加缓冲区大小,直到它起作用。如果你确实增加了堆,希望你不会耗尽内存。

        这是您在运行时设置系统属性的方式。您也可以将它作为参数传递,但我发现在 main 开头附近设置会起到作用,并使未来的开发人员更容易维护项目。

        无论出于何种原因,对于大文件,您没有足够大的缓冲区来加载页面。也许页面在渲染成图像之前或期间被加载到缓冲区中。我的猜测是 PDF 中的 DPI 非常高,无法放入缓冲区。

        【讨论】:

        • 你的答案是完美的,除了最后一段。在“旧”解析器中,当流的长度不正确时使用回推缓冲区,即 PDF 格式错误(“指定的流长度 72435 错误”消息)。在这种情况下,解析器必须“返回”,默认的 pushbackbuffer 长度为 65536,因此“boom”。
        • @guyfleeman 哪里可以找到 pdfbox 的属性列表?
        • 增加后推缓冲区大小后,我得到:java.io.IOException: expected='endstream' actual='' at offset 1537018
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-12-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多