Using a servlet, how do you download multiple file

2019-05-01 12:44发布

问题:

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{}
}

回答1:

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.



回答2:

First create a zip file which contains all the zip files.

Use ServletOutputStream instead of ZipOutputStream.

Then use the below code

protected void doGet(final HttpServletRequest request, final HttpServletResponse response) {
        final String filename = "/usr/local/FileName" + ".zip";

        BufferedInputStream buf = null;
        ServletOutputStream myOut = null;

        try {
            myOut = response.getOutputStream();

            File myfile = new File(filename);

            if (myfile.exists()) {
                //myfile.createNewFile();
                //set response headers
                response.setHeader("Cache-Control", "max-age=60");
                response.setHeader("Cache-Control", "must-revalidate");
                response.setContentType("application/zip");

                response.addHeader("Content-Disposition", "attachment; filename=" + filename);

                response.setContentLength((int) myfile.length());

                FileInputStream input = new FileInputStream(myfile);
                buf = new BufferedInputStream(input);
                int readBytes = 0;

                //read from the file; write to the ServletOutputStream
                while ((readBytes = buf.read()) != -1) {
                    myOut.write(readBytes);
                }
            }

        } catch (Exception exp) {
        } finally {
            //close the input/output streams
            if (myOut != null) {
                try {
                    myOut.close();
                } catch (IOException ex) {
                }
            }
            if (buf != null) {
                try {
                    buf.close();
                } catch (IOException ex) {
                }
            }

        }
    }