java - 如何避免通过 iText7 阅读复杂的 PDF 时内存不足?

标签 java pdf itext itext7

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

例如,单个 PDF 可能只有 33MB,但它包含一个包含 800 页、100 万行的表,而 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
}

Image of heap dump from a complex PdfDocument

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

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

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

最佳答案

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

RandomAccessSourceFactory rasf = new RandomAccessSourceFactory();

RandomAccessSource ras = rasf.createBestSource(file);

RandomAccessFileOrArray rafoa = new RandomAccessFileOrArray(ras);

PdfReader pdfReader = new PdfReader(rafoa, null);

关于java - 如何避免通过 iText7 阅读复杂的 PDF 时内存不足?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57828508/

相关文章:

java - 如何区分可搜索的 pdf 和不可搜索的 pdf?

javascript - 使用 SAPUI5 中响应表的实时数据生成 PDF 文件

java - itext 将 PDF 分割成多个 PDF,但大小相同

java - 如何识别音频流格式?

java - handler.postDelayed 无法正常工作

java - 如何在 IText 7 中设置现有 PDF 的 pdf 版本?

pdf - 使用 iText 库将 pdf 转换为 pdf/a

java - 为什么这段代码会抛出 java.lang.StackOverflowError

java - Hibernate 4.3 通过具有嵌入式 ID 的多个列表进行级联合并

c# - iTextSharp文档中PageNumber和PageCount的区别