0

Why might the following code be generating a corrupt zip file when output over a servlet output stream? When writing the ZIP to disk locally using a FileOutputStream, the output stream does not appear to be corrupt.

// Create zip stream
ZipOutputStream zos = new ZipOutputStream(this.servletOutputStream);

// prepare a new entry
ZipEntry zipEntry = new ZipEntry(forZip.getName());
zipEntry.setSize(forZip.getTotalSpace());
zipEntry.setTime(System.currentTimeMillis());

// write entry
zos.putNextEntry(zipEntry);

// write the file to the entry
FileInputStream toBeZippedInputStream = new FileInputStream(forZip);
IOUtils.copy(toBeZippedInputStream, zos);
zos.flush();

// close entry
zos.closeEntry();

// close the zip
zos.finish();
zos.close();

this.servletOutputStream.flush();

this.servletOutputStream.close();

// close output stream
IOUtils.closeQuietly(toBeZippedInputStream);

Is this perhaps an issue with order of flushing/closing streams?

Hooplator15
  • 1,540
  • 7
  • 31
  • 58
  • You may wanted to flush the `toBeZippedInputStream`instead of the `zos`? – LostKatana Jan 05 '17 at 18:45
  • How are you determining that stream data are corrupt? – John Bollinger Jan 05 '17 at 18:52
  • How are you sure that the problem is not in the code that you did not present? If it's this code that's faulty then it shouldn't be too hard to prepare and present a [mcve]. – John Bollinger Jan 05 '17 at 18:54
  • In particular, my first guess would be that something gets written to the output stream before the Zip data. – John Bollinger Jan 05 '17 at 18:56
  • You might want to read about [what getTotalSpace() does](http://docs.oracle.com/javase/8/docs/api/java/io/File.html#getTotalSpace--). You should just remove that line entirely; you don’t need to set a ZipEntry’s size explicitly. – VGR Jan 05 '17 at 20:37

2 Answers2

1

Try closing the zip entry before flushing the zip stream

// close entry
zos.closeEntry();

zos.flush();

On the coding style, use try-with-resources to make sure the resources are closed properly.

neurite
  • 2,798
  • 20
  • 32
  • I would not recommend flushing. In my case it caused corrupted output in servlet. Using just finish() helped me. – Simon Logic Sep 16 '20 at 17:14
0

A potential problem I see is that the individual entries to be zipped are not unique. If you are looping through in this code, forZip.getName() may have duplicates.

Das_Geek
  • 2,775
  • 7
  • 20
  • 26
  • This is a question about the original question, not an answer. Please delete this, and add it to the comments section of this thread. – Vendetta Feb 19 '20 at 15:25