【问题标题】:How to make streamed PDF merging without memory consumption?如何在不消耗内存的情况下进行流式 PDF 合并?
【发布时间】:2018-02-06 12:26:29
【问题描述】:

我需要将许多小 pdf 文件合并为一个大 pdf (~200G)。而且我找不到可以在不吃掉我所有记忆的情况下做到这一点的库/工具。

我看了 itext、pdfbox、pdftk。但似乎它们都将文件存储在内存中。根据 pdf 文件结构,它应该很容易按顺序获取输入文档流并写入结果文件,只在内存中保存外部参照表。

我用来测试 iText 的代码。每个下一个文件都会消耗越来越多的内存:

public static void MergePDFs(String[] fileNames, String targetPdf) throws IOException, DocumentException {
    FileOutputStream stream = new FileOutputStream(targetPdf);
    Document document = new Document();
    PdfCopy pdf = new PdfCopy(document, stream);
    PdfReader reader = null;
    document.open();
    for (String file : fileNames) {
        reader = new PdfReader(file);
        pdf.addDocument(reader);
        pdf.freeReader(reader);
        reader.close();
    }
    if (reader != null) {
        reader.close();
    }
    document.close();
    stream.close();
}

【问题讨论】:

  • PDFBox 可以使用暂存文件,请参阅public void mergeDocuments(MemoryUsageSetting memUsageSetting)。作为一种工具,请尝试基于 PDFBox fork 的 pdfsam。
  • IText 有多种方法来构建具有不同内存使用的 pdf 阅读器和编写器。因此:您尝试过什么?
  • @mkl 对于千兆字节大小的文件的特定用例,没有一个 PDF 库可以在不使用特殊策略的情况下一次性完成。这是一个已知问题。
  • @mkl 添加代码到问题
  • @AmedeeVanGasse 是的。但即使分组进行,也可以而且应该优化内存使用。

标签: pdf memory itext pdfbox pdftk


【解决方案1】:

一种策略是以 10 个文件为一组进行合并,然后合并中间文件。根据需要采取尽可能多的中间步骤。例如:

  • 步骤 0:1 页 1000 个文件
  • 第 1 步:100 个文件,共 10 页
  • 第 2 步:10 个文件,共 100 页
  • 第 3 步:1 个文件,共 1000 页

没有固定的规则,我说的是 10,但也许对你来说最佳的解决方案是每 8 或每 14,你必须进行实验。

理论上,您甚至可以在不同的机器上并行运行中间步骤,这可以显着加快合并速度,但需要更多硬件。

我的回答很笼统,适用于任何 pdf 库,但在 iText Software,我们所做的研究表明,这种策略更快且占用内存更少。

【讨论】:

  • 无论如何,最后我需要合并两个大文件。尝试使用 iText 合并两个 14Gb pdf,将 partial=true 传递给 PdfReader 并消耗 12Gb 内存
  • 但是它会抛出 OutOfMemoryError 吗?
  • 不,iText 进行了合并。但最终我需要合并 140Gb 文件,并且 120Gb RAM 内存消耗是不可接受的
  • 这是因为 iText 尝试以智能方式合并文件,通过重用文件中已有的对象,而不是保留相同对象的多个相同副本。这通常会产生较小的文件。为了能够做到这一点,对象必须保存在某处,这会导致内存使用。
  • 我使用 PdfCopy 类,而不是 PdfSmartCopy。我认为它不应该使用这种技术
猜你喜欢
  • 2016-04-18
  • 1970-01-01
  • 1970-01-01
  • 2021-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-09
  • 2019-09-25
相关资源
最近更新 更多