【问题标题】:iText - OutOfMemory creating more than 1000 PDFsiText - OutOfMemory 创建超过 1000 个 PDF
【发布时间】:2015-12-29 18:20:56
【问题描述】:

我想创建一个充满 PDF-As 的 ZipOutputStream。我正在使用 iText(版本 5.5.7)。对于 1000 多个 pdf 条目,我在 doc.close() 上收到 OutOfMemory 异常并且找不到泄漏。

ByteArrayOutputStream baos = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(baos));
zos.setEncoding("Cp850");
for (MyObject o : objects) {
try {
    String pdfFilename = o.getName() + ".pdf";
    zos.putNextEntry(new ZipEntry(pdfFilename));
    pdfBuilder.buildPdfADocument(zos);
    zos.closeEntry();
} ...

PdfBuilder

public void buildPdfADocument(org.apache.tools.zip.ZipOutputStream zos){
   Document doc = new Document(PageSize.A4);
   PdfAWriter writer = PdfAWriter.getInstance(doc, zos, PdfAConformanceLevel.PDF_A_1B);
   writer.setCloseStream(false); // to not close my zos
   writer.setViewerPreferences(PdfWriter.ALLOW_PRINTING | PdfWriter.PageLayoutSinglePage);
   writer.createXmpMetadata();
   doc.open();
   // adding Element's to doc
   // with flushContent() on PdfPTables
   InputStream sRGBprofile = servletContext.getResourceAsStream("/WEB-INF/conf/AdobeRGB1998.icc");
   ICC_Profile icc = ICC_Profile.getInstance(sRGBprofile);
   writer.setOutputIntents("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1", icc);
   //try to close/flush everything possible
   doc.close();
   writer.setXmpMetadata(null);
   writer.flush();
   writer.close();
   if(sRGBprofile != null){
     sRGBprofile.close();
   }
}

有什么建议可以解决吗?我是不是忘记了什么? 我已经尝试过使用 java ZipOutputStream 但它有什么不同。


谢谢你的回答!我了解 ByteOutputStream 的问题,但我不确定在我的情况下最好的方法是什么。这是一个 Web 应用程序,我需要以某种方式将 zip 打包到数据库 blob 中。

我现在正在做的是使用 iText 将 PDF 直接创建到 ZipOutputStream 中,并将相应 ByteArrayOutputSteam 的字节数组保存到 blob。我看到的选项是:

将我的数据拆分为 500 个对象包,将前 500 个 PDF 保存到数据库中,然后打开 zip 并添加接下来的 500 个,依此类推...但我认为这会造成与现在相同的情况,即内存中打开的流太大。

尝试将 PDF 保存在服务器上(不确定是否有足够的空间),创建临时 zip 文件,然后将字节提交到 blob...

有什么建议/想法吗?

【问题讨论】:

  • 不要使用 ByteArrayOutputStream,因为这会在内存中构建整个 zip 文件。尝试改用 FileOutputStream。
  • 如果 ZIP 如此之大,它已经使服务器端 vm(通常给予相当多的内存)内存不足,那么这肯定是使用硬而是将磁盘空间流式传输到 DB(如果有问题的 DB 提供了这样一个真正的流式传输接口,即)。话虽如此,将这么大的 ZIP 存储在单个 BLOB 中真的有意义吗?每个 PDF 一个 BLOB 的 DB 设计不是更灵活吗?

标签: java pdf out-of-memory itext zipoutputstream


【解决方案1】:

这是因为您的 ZipOutputStream 由 ByteArrayOutputStream 支持,因此即使关闭条目也会将完整的 ZIP 内容保留在内存中。

【讨论】:

    【解决方案2】:

    您需要使用另一种方法来处理这么多参数(1000 多个文件)。

    您正在将所有 PDF 文件加载到您的示例的内存中,您需要在文档块中执行此操作,以最大限度地减少这种“内存加载”的影响。

    另一种方法是在文件系统上序列化您的 PDF,然后创建您的 zip 文件。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-04
      • 2016-03-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多