0

Using zip4j lib I can create a zip file from a folder which contain subfolders and files. But now I want to download it to the client by Rest API, so I use ZipOutputStream but I don't know how to get the InputStream from generated zip file.

Method to generate zip file.

public void generateBulkConfigFile(HttpServletResponse response, String root, String zippedFileName) {

    File rootFolder = FileUtil.createRootFolder(root);
    response.setStatus(HttpServletResponse.SC_OK);
    response.addHeader("Content-Disposition", "attachment; filename=\"" + "test.zip" + "\"");

    ZipParameters zipParameters = new ZipParameters();
    zipParameters.setEncryptFiles(true);
    zipParameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_STANDARD);
    zipParameters.setPassword("1234");

    //Code to process data, write files and subfolders to root folder

    try {
        ZipFile zipFile = new ZipFile(rootFolder.getAbsolutePath() +  System.lineSeparator() + zippedFileName + ".zip");
        zipFile.addFolder(rootFolder, zipParameters);

        //Todo: get inputstream from zipped file and write to response outputstream for client

    } catch (ZipException e) {
        log.error("Error: ", e);
        throw e;
    } catch (IOException e) {
        log.error("Error: ", e);
        throw e;
    }
}

The above code successfully created the zip file in desired folder. I tried adding this lines of code to output to response.

ZipOutputStream zipOutputStream = new ZipOutputStream(response.getOutputStream());
FileInputStream fileInputStream = new FileInputStream(zipFile.getFile());
IOUtils.copy(fileInputStream, zipOutputStream);

fileInputStream.close();
zipOutputStream.finish();
zipOutputStream.close();

But it end up with the NullPointerException in the copy method of IOUtils class.

java.lang.NullPointerException: null
at net.lingala.zip4j.io.DeflaterOutputStream.write(DeflaterOutputStream.java:89) ~[zip4j-1.3.3.jar:?]
at net.lingala.zip4j.io.ZipOutputStream.write(ZipOutputStream.java:31) ~[zip4j-1.3.3.jar:?]
at org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:1793) ~[commons-io-2.4.jar:2.4]
at org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:1769) ~[commons-io-2.4.jar:2.4]
at org.apache.commons.io.IOUtils.copy(IOUtils.java:1744) ~[commons-io-2.4.jar:2.4]

Can someone help me to get through this problem? Thanks a lot.

Thong Vo
  • 809
  • 1
  • 9
  • 21
  • Why would you copy the zip file in another stream if the file exists? All it will achieve is duplicating the file. Don't you just want to return an `InputStream` to your user? – Dici Aug 19 '19 at 06:52
  • @Dici It does not duplicate the file, all I need is to copy the content of the created file to the outputstream for client to download it. – Thong Vo Aug 19 '19 at 07:02
  • Ah yeah sorry you're writing to the response output stream, misread – Dici Aug 19 '19 at 07:06
  • However, why are you wrapping the response stream into a `ZipOutputStream`? The bytes you get from the input stream are already zipped, in your stacktrace you see that the library is trying to compress (deflate) the data again. – Dici Aug 19 '19 at 07:09

1 Answers1

1

How about just

try (Outpustream os = response.getOutputStream(); 
     InputStream fis = new FileInputStream(zipFile.getFile())) {
    IOUtils.copy(fis, os);
}

You don't need to wrap the output stream in ZipOutputStream because the bytes you're putting in are already zipped. It's up to the client on the other side to consume these bytes and inflate them back.

Dici
  • 25,226
  • 7
  • 41
  • 82
  • Very nice, I didn't noticed it. Thank you. – Thong Vo Aug 19 '19 at 07:17
  • No prob, by the way I also added a `try-catch with resources` in my answer because it's better than manually closing streams. It will ennsure that whatever exception occursor not, the streams or resources will be closed. Feel free to accept the answer if this fixed your issue ^^ – Dici Aug 19 '19 at 07:20