Spring REST - create .zip file and send it to the client

I want to create .zip file that contains my zipped files that I recieve from backend, and then send this file to the user. For 2 days I have been looking for the answer and cant find proper solution, maybe you can help me :)

For now, the code is like this: (I know I shouldnt do it all in the spring controller, but dont care about that, it is just for testing purposes, to find the way to make it works)

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

        //creating byteArray stream, make it bufforable and passing this buffor 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();
    }

But the problem is, that using the code, when I enter URL: localhost:8080/zip I get file: test.zip.html instead of .zip file

When I remove .html extension and leave just test.zip it opens correctly how to avoid returning this .html extension? why is it added?

I have no idea what else can I do. I was also trying replace ByteArrayOuputStream with something like:

OutputStream outputStream = response.getOutputStream();

and set the method to be void so it returns nothing, but It created .zip file which was.. damaged?

On my macbook after unpacking the test.zip I was getting test.zip.cpgz which was again giving me test.zip file and so on..

On windows the .zip file was damaged as I said and couldn't even open it.

I also suppose, that removing .html extension automatically will be the best option, but how? Hope it is no as hard as It seems to be :) thanks


seems to be solved. I replaced:

response.setContentType("application/zip");

with:

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

And now I get clear, beautiful .zip file :)

If any of you have either better or faster proposition, or just want to give some advice, then go ahead, I am curious.


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