如何为“虚拟文件”列表创建ZIP文件并输出到httpservletresponse

时间:2011-01-13 21:28:05

标签: java spring servlets spring-mvc zip

我的目标是将多个java.io.File对象放入zip文件并打印到HttpServletResponse以供用户下载。

这些文件是由JAXB marshaller创建的。它是一个java.io.File对象,但它实际上并不在文件系统上(它只在内存中),因此我无法创建FileInputStream。

我见过的所有资源都使用OutputStream来打印zip文件内容。但是,所有这些资源都使用FileInputStream(我无法使用)。

任何人都知道如何做到这一点?

2 个答案:

答案 0 :(得分:6)

查看Apache Commons Compress库,它提供了您需要的功能。

当然,“erickson”对你的问题的评论是正确的。您将需要文件内容而不是java.io.File对象。在我的例子中,我假设你有一个方法 byte[] getTheContentFormSomewhere(int fileNummer)返回fileNummer-th文件的文件内容(在内存中)。 - 当然这个功能设计很差,但它仅用于说明。

应该有点像这样:

void compress(final OutputStream out) {
  ZipOutputStream zipOutputStream = new ZipOutputStream(out);
  zipOutputStream.setLevel(ZipOutputStream.STORED);

  for(int i = 0; i < 10; i++) {
     //of course you need the file content of the i-th file
     byte[] oneFileContent = getTheContentFormSomewhere(i);
     addOneFileToZipArchive(zipOutputStream, "file"+i+"."txt", oneFileContent);
  }

  zipOutputStream.close();
}

void addOneFileToZipArchive(final ZipOutputStream zipStream,
          String fileName,
          byte[] content) {
    ZipArchiveEntry zipEntry = new ZipArchiveEntry(fileName);
    zipStream.putNextEntry(zipEntry);
    zipStream.write(pdfBytes);
    zipStream.closeEntry();
}

你的http控制器的Snipets:

HttpServletResponse response
...
  response.setContentType("application/zip");
  response.addHeader("Content-Disposition", "attachment; filename=\"compress.zip\"");
  response.addHeader("Content-Transfer-Encoding", "binary");
  ByteArrayOutputStream outputBuffer = new ByteArrayOutputStream();
  compress(outputBuffer);
  response.getOutputStream().write(outputBuffer.toByteArray());
  response.getOutputStream().flush();
  outputBuffer.close();

答案 1 :(得分:3)

原来我是个白痴:)正在“创建”的文件正在保存到无效路径并吞下异常,所以我认为它被“创建”了。但是,当我试图实例化一个新的FileInputStream时,它抱怨该文件不存在(这是正确的)。我有一个brainfart并假设java.io.File对象实际上在某处包含文件信息。但正如埃里克森指出的那样,这是错误的。

感谢Ralph的代码,我在解决了无效的路径问题后使用了它。

我的代码:

ZipOutputStream out = new ZipOutputStream(response.getOutputStream());
byte[] buf = new byte[1024];

File file;
InputStream in;
// Loop through entities
for (TitleProductAccountApproval tpAccountApproval : tpAccountApprovals) {
    // Generate the file    
    file = xmlManager.getXML(
        tpAccountApproval.getTitleProduct().getTitleProductId(), 
        tpAccountApproval.getAccount().getAccountId(), 
        username);

    // Write to zip file
    in = new FileInputStream(file);
    out.putNextEntry(new ZipEntry(file.getName()));

    int len;
    while ((len = in.read(buf)) > 0) {
        out.write(buf, 0, len);
    }

    out.closeEntry();
    in.close();
}

out.close();