Search code examples
javazipfileoutputstreambytearrayoutputstream

Java Zip File Created With ByteArrayOutputStream is smaller than with FileOutputStream


The Zip file output from using ByteArrayOuputStream is smaller than that with FileOutputStream.

In Java I am creating a Zip file. Which opens successfully when I use FileOutputStream.

When switching the FileOutputStream to a ByteArrayOutputStream I get a slightly smaller file, about 221 bytes. And this file won't open, but has the same contents as the other but missing 221 bytes.

The logic I use to construct the Zip file is the same in both cases. Therefore I will share the essential logic without the zip creation (let me know if you need this).

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        zipOS = new ZipOutputStream(baos);

Then I create the Zip file, and then ...

        zipOS.flush();
        baos.flush();
        baos.writeTo(new FileOutputStream("TEST_AS_BYTESTREAM_1.zip"));
        zipOS.close();
        baos.close();

I'm using the baos.writeTo() to bypass this to prove it's not the HTTP response but the ByteArrayOutputStream element thats an issue.

When using baos.writeTo(new FileOutputStream("TEST_AS_BYTESTREAM_1.zip")); I get a smaller file that doesn't open as a Zip.

This logic is in a java controller so that a link clicked on web page will down load the zip file without touching any file systems excepted the users.

Here is the code using FileOutputStream which works...

        FileOutputStream baos = new FileOutputStream("TEST_AS_FILE.zip");
        zipOS = new ZipOutputStream(baos);

Aside from the the second code snippet isn't relevant as I would need to send the file created on the web server. But the point is, that Fileoutput stream with the same logic and ByteArrayOutputStream has a difference.


Solution

  • The final answer is as follows. Many thanks to the answer previously given.

    Basically I needed to use the .finish() method of the ZipOuputStream. Everything else remained the same.

    Pre zip creation code same as before

            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            zipOS = new ZipOutputStream(baos);
    

    Post zip creation...

            zipOS.flush();
            zipOS.finish();
            baos.flush();
            documentBody = baos.toByteArray();
            zipOS.close();
            baos.close();
    

    Then my HTTP response is

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(new MediaType("application", "zip"));
        headers.setContentLength(documentBody.length);
        headers.add("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
        ByteArrayResource resource = new ByteArrayResource(documentBody);
    
        return ResponseEntity.ok()
                .headers(headers)
                .body(resource);
    

    This way I avoid the creation of a file which is nice.

    Many thanks for the assistance.