Using a servlet, how do you download multiple files from a database and zip them for client download

Lani1234 picture Lani1234 · Apr 12, 2013 · Viewed 17.7k times · Source

I have a jsp/servlet web app in which the client can choose a "course" and an "assignment" via dropdown boxes, and then click a button to download all the files in the database that are listed under that course/assignment combination. The servlet code isn't quite working, as the zip file is not being sent to the browser as an attachment. I do have working code for downloading one file at a time, but something is getting stuck with this code for zipping the files. All the files in the database are actually zip files themselves, so I am trying to zip up a bunch of zip files. I didn't think this would require that they be treated differently than zipping any other format of files. Can anyone see what is missing? Here is my doGet method code in the servlet that handles the downloading. Much of this code was found here on stackoverflow. Please note that the FileSubmitted object is my DOA containing all the file info for each file in the database, including the Blob itself:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
    List<FileSubmitted> fileList = new ArrayList<FileSubmitted>();
    String course= request.getParameter("course");
    String assignment = request.getParameter("assignment");

    java.sql.PreparedStatement pstmt = null;
    java.sql.Connection conn = null;
    ResultSet rs;
    String queryString;

    try {
        conn = ConnectionManager.getConnection();
        conn.setAutoCommit(false);

        queryString = "SELECT * FROM files WHERE courseID=\""+course+"\" AND assignmentID=\""+assignment+"\";";
        pstmt = conn.prepareStatement(queryString);
        rs = pstmt.executeQuery(queryString);
        while(rs.next())
        {
            fileList.add(new FileSubmitted(rs.getString("username"),
                                           rs.getString("courseID"),
                                           rs.getString("assignmentID"),
                                           rs.getString("fileName"),
                                           rs.getString("mimeType"),
                                           (Blob) rs.getBlob("contents")));
        }


        response.setContentType("application/zip");
        response.setHeader("Content-Disposition", "attachment; filename=\"allfiles.zip\"");

        ZipOutputStream output = null;
        byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];

        try {
            output = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream(), DEFAULT_BUFFER_SIZE));

            for (FileSubmitted file : fileList)
            {
                InputStream input = null;
                try {
                        input = new BufferedInputStream(file.getContents().getBinaryStream(), DEFAULT_BUFFER_SIZE);
                        output.putNextEntry(new ZipEntry(file.getFileName()));
                        for (int length = 0; (length = input.read(buffer)) > 0;)
                        {
                            output.write(buffer, 0, length);
                        }
                    }//try
                    catch (SQLException e) {e.printStackTrace();}
                    finally{}
                    output.closeEntry();
            }//for
          }//try
          finally{}
     } 
     catch (Exception e1) {e1.printStackTrace();}
     finally{}
}

Answer

Lani1234 picture Lani1234 · Apr 14, 2013

In case this can be helpful to anyone else, I found the answer to the problem. The code posted above actually works perfectly for downloading multiple files from a database and creating a zip file for the client to download. The problem was that I was calling the servlet via ajax, and apparently you can't download files via an ajax call. So I changed my jsp page to call the servlet via submitting a form, and then the download came through to the browser perfectly.