The example below is a servlet
that shows you how to create a zip file and send the generated zip file for user to download. The compressing process is done by the zipFiles
method of this class.
For a servlet
to work you need to configure it in the web.xml
file of your web application which can be found after the code snippet below.
package org.kodejava.servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@WebServlet(urlPatterns = "/zipservlet")
public class ZipDownloadServlet extends HttpServlet {
public static final String FILE_SEPARATOR = System.getProperty("file.separator");
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
// The path below is the root directory of data to be
// compressed.
String path = getServletContext().getRealPath("data");
File directory = new File(path);
String[] files = directory.list();
// Checks to see if the directory contains some files.
if (files != null && files.length > 0) {
// Call the zipFiles method for creating a zip stream.
byte[] zip = zipFiles(directory, files);
// Sends the response back to the user / browser. The
// content for zip file type is "application/zip". We
// also set the content disposition as attachment for
// the browser to show a dialog that will let user
// choose what action will he do to the content.
ServletOutputStream sos = response.getOutputStream();
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment; filename=\"DATA.ZIP\"");
sos.write(zip);
sos.flush();
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Compress the given directory with all its files.
*/
private byte[] zipFiles(File directory, String[] files) throws IOException {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(baos)) {
byte[] bytes = new byte[2048];
for (String fileName : files) {
String path = directory.getPath() +
ZipDownloadServlet.FILE_SEPARATOR + fileName;
try (FileInputStream fis = new FileInputStream(path);
BufferedInputStream bis = new BufferedInputStream(fis)) {
zos.putNextEntry(new ZipEntry(fileName));
int bytesRead;
while ((bytesRead = bis.read(bytes)) != -1) {
zos.write(bytes, 0, bytesRead);
}
zos.closeEntry();
}
}
zos.close();
return baos.toByteArray();
}
}
}
Maven dependencies
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
Latest posts by Wayan (see all)
- How do I get number of each day for a certain month in Java? - September 8, 2024
- How do I get operating system process information using ProcessHandle? - July 22, 2024
- How do I sum a BigDecimal property of a list of objects using Java Stream API? - July 22, 2024
Nice post, done exactly the same with my servlet.
The files I need to ZIP are stored as BLOB and add them as
byte[]
. When I add them as aZIPEntry
everything works fine, but when I review the exported files, they don’t have a content type individually and marked as invalid content, any recommendations?Have you check if the BLOB data is correctly read from the database and the
byte[]
contains all the content of the BLOB?Hi there,
I used your code, it works great!, well I haven’t tested it with real data but it seems to be working fine, one question, where is the “data” folder in your example?
Thank you!
Hi Miguel,
In this case the data directory should be under you webapp root directory. For example if your web application root directory is webapp then the data should be webapp/data. I hope that helps you.
Hi Dude,
It works good.
Thanks buddy…
I tried running the code in jsp, then I can get a getOutputStream() has already been called for this response. any idea for this?
Nice! Great! it really helped me. Thanks
You’re welcome Stanley.
Great
Thanks your solution is working perfectly but i want to download folder which contain subfolders
Hi Riaz, for your requirement you can try the following example: How do I compress or zip a directory recursively?
Thanks. I was stuck. Because i was exporting to bytes before closing the the zos. This opened my eyes.
How to send this response to JSP.
Thank you, but how do you write the javascript codes? thanks
This solution won’t work for large files as there is a
byte[] zip = zipFiles(directory, files);
in it. The resulting file has to fit into memory. Prefer using directly the Servlet outputStream by wrapping it into theZipOutputStream
.ZipOutputStream zos = new ZipOutputStream(response.getOutputStream());
That way, you will consume less memory.