【问题标题】:How to avoid running out of memory reading a complex PDF via iText7?如何避免通过 iText7 读取复杂 PDF 时内存不足?
【发布时间】:2019-09-06 20:59:05
【问题描述】:

我正在使用 iText7 和 Java 来读取不是很大 (10-30MB) 的 PDF,但它们包含大量对象,在创建和使用 PdfDocument 时会导致 OutOfMemoryError 问题。 (内部xref 表和Map/Tree/Pdf[Dict/Array] 对象数以百万计。)

例如,一个 PDF 可能只有 33MB,但它包含一个包含 800 页的一百万行的单个表,而 PdfDocument 内部的簿记容量高达 400MB。这是示例代码和堆转储:

public static void main(String[] args) throws Exception {

    // PDF file is 33MB on disk (one big table over 800 pages)
    File pdf = new File("big.pdf"); // Also tried InputStream

    PdfReader reader = new PdfReader(pdf); // 35MB heap

    PdfDocument document = new PdfDocument(reader); // 400MB+ heap

    // do stuff ... assuming we didn't get an OOM above
}

我们为 JVM 添加了更多内存,但我们不知道其中一些 PDF 可能有多大/复杂,因此需要一个长期的解决方案,理想情况下是让我们可以分段或在事件中读取内容的解决方案- 类回调方式(如 XML+STAX/SAX)。

有没有更有效的方法来流式传输 PDF 或将其分解为子 PdfDocuments 给定文件或 InputStream?我们想要定位和提取表单、表格、工具提示等对象。

更新:我与 IText 团队取得了联系,IText7 不允许部分阅读 PDF。因此,在这种情况下,除了添加更多 RAM 或预解析 PDF mysql 并查找“太多数据”(大量工作)之外,我无能为力。我还检查了PDFBox,它也遇到了同样的问题。

【问题讨论】:

  • 我认为您将 PDF 拆分为最少页数,即 100 页或更适合您的页面,然后执行操作
  • @Vineet1982 - 我在考虑类似的策略,但后来又遇到了同样的问题:如何以编程方式拆分 PDF (PdfSplitter) 我什至一开始都看不懂在没有内存问题的情况下进入 Java?问题是我不知道这些 PDF 来自哪里或它们的复杂性,所以我无法提前手动预拆分它们。
  • 搜索互联网 有很多程序/代码可用于以编程方式拆分 pdf。拆分 PDF 不需要太多内存,它们是专门为此目的而精心创建的。有很多c程序可以用api调用,可以从java调用
  • 也许:64 位 java 中的小对象指针曾经是 JVM 选项。数据修剪:无(嵌入)字体,图像最小化。一个(商业)PDF 优化器。 Linux。
  • 正如我在更新中提到的,IText7 无法解决这个问题。如果在解析对象时有一个事件回调就好了,这样调用代码可以计算解析进度,如果数据太多可能会抛出异常。但是 API 非常封闭。我将继续评估其他解决方案和工具包。

标签: java pdf itext itext7


【解决方案1】:

您可以执行以下操作来读取大文件:

RandomAccessSourceFactory rasf = new RandomAccessSourceFactory();

RandomAccessSource ras = rasf.createBestSource(file);

RandomAccessFileOrArray rafoa = new RandomAccessFileOrArray(ras);

PdfReader pdfReader = new PdfReader(rafoa, null);

【讨论】:

  • 我会将它用于大文件,非常感谢!不幸的是,我在原始帖子中遇到的主要问题与其说是 PDF 的原始大小,不如说是内部内容的复杂性以及 IText 炸毁堆的内部簿记对象。例如,即使是 10MB 的小型 PDF 也可能足够复杂(嵌套对象、表格等),在 IText 中表示它需要数百 MB 的堆。在短期内,我将PdfReader 子类化并在内部跟踪XREF 对象并在达到限制时停止处理。这是一个可怕的 hack,但它保证了服务器的安全。
猜你喜欢
  • 2019-11-09
  • 1970-01-01
  • 1970-01-01
  • 2020-03-26
  • 1970-01-01
  • 2019-05-21
  • 2011-04-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多