How do I create zip file in Servlet for download?

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.example.servlet;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
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;

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 sent 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 {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ZipOutputStream zos = new ZipOutputStream(baos);
        byte bytes[] = new byte[2048];

        for (String fileName : files) {
            FileInputStream fis = new FileInputStream(directory.getPath() + 
                ZipDownloadServlet.FILE_SEPARATOR + fileName);
            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();
            bis.close();
            fis.close();
        }
        zos.flush();
        baos.flush();
        zos.close();
        baos.close();

        return baos.toByteArray();
    }
}

The web.xml configuration:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         id="WebApp_ID" version="2.5">
    <servlet>
        <servlet-name>ZipDownloadServlet</servlet-name>
        <servlet-class>org.kodejava.example.servlet.ZipDownloadServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>ZipDownloadServlet</servlet-name>
        <url-pattern>/zipservlet</url-pattern>
    </servlet-mapping>
</web-app>

How do I create a hit counter servlet?

Here we have a simple example of creating a hit counter using servlet. The servlet updates the hits counter every time a page is visited and display the number of hits as an image. The image is generated at runtime using Java’s Graphic2D and ImageIO class.

To store the hits data create a table hits with a single field called counter and set the initial value of the counter to zero. Below is the HitCounterServlet servlet code.

package org.kodejava.example.servlet;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.sql.*;

public class HitCounterServlet extends HttpServlet {
    public HitCounterServlet() {
        super();
    }

    protected void doGet(HttpServletRequest req, HttpServletResponse res)
            throws ServletException, IOException {
        updateHitCounter();
        getHitCounterImage(req, res);
    }

    protected void doPost(HttpServletRequest request,
                          HttpServletResponse response)
            throws ServletException, IOException {
        updateHitCounter();
        getHitCounterImage(request, response);
    }

    private void updateHitCounter() {
        Connection connection = getConnection();
        try {
            // Update the hits counter table by incrementing the
            // counter every time a user hits our page.
            String sql = "UPDATE hits SET counter = counter + 1";
            PreparedStatement stmt = connection.prepareStatement(sql);
            stmt.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            closeConnection(connection);
        }
    }

    private void getHitCounterImage(HttpServletRequest req,
                                    HttpServletResponse res)
            throws IOException {
        Connection connection = getConnection();
        String hits = "";
        try {
            // Get the current hits counter from database.
            String sql = "SELECT counter FROM hits";
            PreparedStatement stmt = connection.prepareStatement(sql);
            ResultSet rs = stmt.executeQuery();
            while (rs.next()) {
                hits = rs.getString("counter");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            closeConnection(connection);
        }

        // Create an image of our counter to be sent to the browser.
        BufferedImage buffer = new BufferedImage(50, 20, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = buffer.createGraphics();
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        g.setFont(new Font("Monospaced", Font.PLAIN, 14));
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, 50, 20);
        g.setColor(Color.BLACK);
        g.drawString(hits, 0, 20);

        res.setContentType("image/png");
        OutputStream os = res.getOutputStream();
        ImageIO.write(buffer, "png", os);
        os.close();
    }

    private Connection getConnection() {
        Connection connection = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection(
                    "jdbc:mysql://localhost/kodejava", "kodejava", "kodejava123");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return connection;
    }

    private void closeConnection(Connection connection) {
        try {
            if (connection != null && !connection.isClosed()) {
                connection.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

To configure the servlet you’ll need to update the web.xml file as follow:

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
         xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <display-name>kodejava-example</display-name>
    <servlet>
        <display-name>HitCounter</display-name>
        <servlet-name>HitCounter</servlet-name>
        <servlet-class>
            org.kodejava.example.servlet.HitCounterServlet
        </servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>HitCounter</servlet-name>
        <url-pattern>/HitCounter</url-pattern>
    </servlet-mapping>
</web-app>

To display the hits counter image on the JSP page, create an image tag with the source point to our HitCoutnerServlet servlet.

Visited for: <img src="http://localhost:8080/app-name/HitCounter" alt="Hit Counter"/> times.

How do I create a HelloWorld Servlet?

Servlet is a Java solution for creating a dynamic web application, it can be compared with the old CGI technology. Using Servlet we can create a web application that can display information from database, receive information from a web form to be stored on the application database.

This example show the very basic of servlet, it returns a hello world html document for the browser. At the very minimum a servlet will have a doPost() and doGet() method which handles the HTTP POST and GET request.

package org.kodejava.example.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class HelloWorld extends HttpServlet {

    public HelloWorld() {
        super();
    }

    protected void doGet(HttpServletRequest req, HttpServletResponse res) 
            throws ServletException, IOException {
        doPost(req, res);
    }

    protected void doPost(HttpServletRequest req, HttpServletResponse res) 
            throws ServletException, IOException {
        res.setContentType("text/html");

        PrintWriter writer = res.getWriter();
        writer.println("<html>");
        writer.println("<head><title>Hello World Servlet</title></head>");
        writer.println("<body>Hello World! How are you doing?</body>");
        writer.println("</html>");
        writer.close();
    }
}

For a servlet to works on a servlet container such as Apache Tomcat we need to add or register the servlet in the application’s web.xml file. This configuration tells the container about our servlet class and a url that maps a request to the servlet.

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
         xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <display-name>kodejava-example</display-name>
    <servlet>
        <description></description>
        <display-name>HelloWorld</display-name>
        <servlet-name>HelloWorld</servlet-name>
        <servlet-class>
            org.kodejava.example.servlet.HelloWorld
        </servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>HelloWorld</servlet-name>
        <url-pattern>/HelloWorld</url-pattern>
    </servlet-mapping>
</web-app>

When the servlet is deployed to the container we can access it from a url in a form of http://localhost:8080/app-name/HelloWorld.