我想创建一个填充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 ......
有任何建议/想法吗?
答案 0 :(得分:4)
这是因为您的ZipOutputStream
由ByteArrayOutputStream支持,因此即使关闭条目也会将完整的ZIP内容保留在内存中。
答案 1 :(得分:0)
你需要使用另一种方法来处理这个数量的参数(1000多个文件)。
您要在示例中加载内存中的所有PDF文件,您需要在文档块中执行此操作,以最大限度地减少此“内存负载”的影响。
另一种方法是在文件系统上序列化PDF,然后创建zip文件。