1

i try to use Zip4j to generate a zip file for download. But i always get the error:

2015-05-09 15:56:24.306 ERROR 11748 --- [nio-8080-exec-4] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IllegalStateException: getOutputStream() has already been called for this response] with root cause

when calling zout.putNextEntry(file, null); in the function below

public void EmployeeEncyrptedZipFileDownload(HttpServletResponse response, @RequestParam(value = "id", required = true) int employeeId) throws IOException, ZipException
{
    //Prepare text file contents
    String fileContent = "Hallo Welt";

    response.setContentType("application/zip");
    response.setHeader("Content-Disposition", "attachment;filename=test.zip");

    final StringBuilder sb = new StringBuilder(fileContent);
    final ZipOutputStream zout = new ZipOutputStream(response.getOutputStream());

    File file = new File("mytext.txt");
    zout.putNextEntry(file, null);
    byte[] data = sb.toString().getBytes();
    zout.write(data, 0, data.length);

    zout.closeEntry();
    zout.finish();
}

how is that possible, since the putNextEntry function doesn't even get the response but the allready obtained stream?

Matombo
  • 77
  • 1
  • 9

2 Answers2

2

Thats because, the line

zout.putNextEntry(file, null);

is throwing a null pointer because of the null argument. And, since I don't see the rest of your servlet my guess is, your servlet might be trying to fetch the outputstream again to handle/throw this exception.

The second parameter in the above putNextEntry() call is the ZipParameters. As the name describes, this argument specify various zip parameters, for example if the zip is password protected, or if the content of the zip is read form a file or from an input stream, etc. And this is a required argument.

The first parameter of this call is a File object. This is only required if you are building a zip from local file streams. If you are building a zip from external streams (such as in your case), this parameter can be null. I know this is not a good design and will be fixed in the upcoming releases.

Fix for your scenario is:

public void EmployeeEncyrptedZipFileDownload(HttpServletResponse response, @RequestParam(value = "id", required = true) int employeeId) throws IOException, ZipException
{
    //Prepare text file contents
    String fileContent = "Hallo Welt";

    response.setContentType("application/zip");
    response.setHeader("Content-Disposition", "attachment;filename=test.zip");

    final StringBuilder sb = new StringBuilder(fileContent);
    final ZipOutputStream zout = new ZipOutputStream(response.getOutputStream());

    ZipParameters zipParameters = new ZipParameters();
    zipParameters.setSourceExternalStream(true);
    zipParameters.setFileNameInZip("mytext.txt");

    zout.putNextEntry(null, zipParameters);
    byte[] data = sb.toString().getBytes();
    zout.write(data, 0, data.length);

    zout.closeEntry();
    zout.finish();
}
  • thanks that works now, but i have another method where the parameters wasn't null but: ZipParameters parameters = new ZipParameters(); parameters.setEncryptFiles(true); parameters.setPassword("AMOS"); I have added the new parameters: parameters.setSourceExternalStream(true); parameters.setFileNameInZip("employee.txt"); but it still doesn't work, any guess on that? – Matombo May 19 '15 at 19:48
1

If someone need to Zip files with password encryption using Zip4j library, here is a code (as mentioned here):

public void zipFileWithPassword(String fileToZipPath,String password,String zippedFilePath) throws ZipException
{
    ZipFile zipFile=new ZipFile(zippedFilePath);
    ZipParameters parameters=new ZipParameters();
    parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
    parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
    parameters.setEncryptFiles(true);
    parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_STANDARD);
    parameters.setPassword(password);
    File fileToZip=new File(fileToZipPath);
    log(Severity.INFO,"Creating a ZIP file: %s",fileToZipPath);
    zipFile.addFile(fileToZip,parameters);
}

Hope I've helped someone...

Woody
  • 1,589
  • 14
  • 16