1

我尝试使用 Zip4j 生成一个 zip 文件以供下载。但我总是得到错误:

2015-05-09 15:56:24.306 错误 11748 --- [nio-8080-exec-4] oaccC[.[.[/].[dispatcherServlet]:Servlet.service() 用于 servlet [dispatcherServlet] path [] 抛出异常 [请求处理失败;嵌套异常是 java.lang.IllegalStateException: getOutputStream() 已经为此响应调用] 根本原因

当调用 zout.putNextEntry(file, null); 在下面的函数中

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();
}

这怎么可能,因为 putNextEntry 函数甚至没有得到响应,而是已经获得了流?

4

2 回答 2

2

那是因为,线

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();
}
于 2015-05-17T11:48:51.213 回答
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...

于 2015-11-17T13:32:59.530 回答