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-файла.