Spring REST - 创建ZIP文件并将其发送到客户端

2022-08-31 20:14:34

我想创建一个 ZIP 文件,其中包含我从后端收到的存档文件,然后将此文件发送给用户。2天来,我一直在寻找答案,但找不到合适的解决方案,也许你可以帮我:)

就目前而言,代码是这样的(我知道我不应该在Spring控制器中完成所有操作,但不要在乎这一点,它只是为了测试目的,找到使其工作的方法):

    @RequestMapping(value = "/zip")
    public byte[] zipFiles(HttpServletResponse response) throws IOException {
        // Setting HTTP headers
        response.setContentType("application/zip");
        response.setStatus(HttpServletResponse.SC_OK);
        response.addHeader("Content-Disposition", "attachment; filename=\"test.zip\"");

        // Creating byteArray stream, make it bufferable and passing this buffer to ZipOutputStream
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(byteArrayOutputStream);
        ZipOutputStream zipOutputStream = new ZipOutputStream(bufferedOutputStream);

        // Simple file list, just for tests
        ArrayList<File> files = new ArrayList<>(2);
        files.add(new File("README.md"));

        // Packing files
        for (File file : files) {
            // New zip entry and copying InputStream with file to ZipOutputStream, after all closing streams
            zipOutputStream.putNextEntry(new ZipEntry(file.getName()));
            FileInputStream fileInputStream = new FileInputStream(file);

            IOUtils.copy(fileInputStream, zipOutputStream);

            fileInputStream.close();
            zipOutputStream.closeEntry();
        }

        if (zipOutputStream != null) {
            zipOutputStream.finish();
            zipOutputStream.flush();
            IOUtils.closeQuietly(zipOutputStream);
        }
        IOUtils.closeQuietly(bufferedOutputStream);
        IOUtils.closeQuietly(byteArrayOutputStream);

        return byteArrayOutputStream.toByteArray();
    }

但问题是,使用代码,当我输入URL时,我得到一个文件而不是文件。localhost:8080/ziptest.zip.html.zip

当我删除扩展名并只留下它时,它会正确打开。所以我的问题是:.htmltest.zip

  • 如何避免返回此扩展名?.html
  • 为什么添加它?

我不知道我还能做些什么。我也试图用这样的东西替换:ByteArrayOuputStream

OutputStream outputStream = response.getOutputStream();

并将方法设置为void,以便它不返回任何内容,但它创建了已损坏的文件?.zip

在我的MacBook上,打开包装后,我得到了再次给我文件等等。test.ziptest.zip.cpgztest.zip

在Windows上,正如我所说,.zip文件已损坏,甚至无法打开它。

我还认为,自动删除扩展名将是最佳选择,但是如何呢?.html

希望它不像它似乎那么难 :)
谢谢


答案 1

问题解决了。

我替换了:

response.setContentType("application/zip");

跟:

@RequestMapping(value = "/zip", produces="application/zip")

现在我得到了一个清晰,美丽的文件。.zip


如果你们中的任何一个人有更好或更快的主张,或者只是想给出一些建议,那么请继续,我很好奇。


答案 2
@RequestMapping(value="/zip", produces="application/zip")
public void zipFiles(HttpServletResponse response) throws IOException {

    //setting headers  
    response.setStatus(HttpServletResponse.SC_OK);
    response.addHeader("Content-Disposition", "attachment; filename=\"test.zip\"");

    ZipOutputStream zipOutputStream = new ZipOutputStream(response.getOutputStream());

    // create a list to add files to be zipped
    ArrayList<File> files = new ArrayList<>(2);
    files.add(new File("README.md"));

    // package files
    for (File file : files) {
        //new zip entry and copying inputstream with file to zipOutputStream, after all closing streams
        zipOutputStream.putNextEntry(new ZipEntry(file.getName()));
        FileInputStream fileInputStream = new FileInputStream(file);

        IOUtils.copy(fileInputStream, zipOutputStream);

        fileInputStream.close();
        zipOutputStream.closeEntry();
    }    

    zipOutputStream.close();
}