iText - OutOfMemory создает более 1000 PDF-файлов

Я хочу создать ZipOutputStream, заполненный PDF-As. Я использую iText (версия 5.5.7). Для более 1000 записей в формате PDF я получаю исключение OutOfMemory для doc.close () и не могу найти утечку.

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, но я не уверен, каков наилучший подход в моем случае. Это веб-приложение, и мне нужно как-то упаковать zip в блоб базы данных.

То, что я делаю сейчас, - это создание PDF-файлов непосредственно в ZipOutputStream с помощью iText и сохранение байтового массива соответствующего ByteArrayOutputSteam для блобирования. Варианты, которые я вижу:

Разделите мои данные на 500 пакетов объектов, сохраните первые 500 PDF-файлов в базе данных, а затем откройте zip и добавьте следующие 500 пакетов и т. Д. Но я предполагаю, что это создает мне ту же ситуацию, что и сейчас, а именно слишком большую поток открылся в памяти.

Попробуйте сохранить PDF-файлы на сервере (не уверен, достаточно ли места), создать временный zip-файл, а затем отправить байты в BLOB-объект...

Любые предложения / идеи?

2 ответа

Это потому что твой ZipOutputStream поддерживается ByteArrayOutputStream, поэтому даже закрытие записей сохраняет все содержимое ZIP в памяти.

Вам нужно использовать другой подход, чтобы сделать это с таким количеством аргументов (более 1000 файлов).

Вы загружаете все файлы PDF в память на вашем примере, вам нужно будет сделать это в блоках документов, чтобы минимизировать эффект этой "загрузки памяти".

Другой подход заключается в сериализации ваших PDF-файлов в файловой системе, а затем в создании zip-файла.

Другие вопросы по тегам