【问题标题】:Using a servlet, how do you download multiple files from a database and zip them for client download使用 servlet,如何从数据库中下载多个文件并将其压缩以供客户端下载
【发布时间】:2013-04-12 02:37:25
【问题描述】:

我有一个 jsp/servlet Web 应用程序,客户端可以在其中通过下拉框选择“课程”和“作业”,然后单击按钮下载该课程下列出的数据库中的所有文件/作业组合。 servlet 代码不能正常工作,因为 zip 文件没有作为附件发送到浏览器。我确实有一次下载一个文件的工作代码,但是这个用于压缩文件的代码卡住了一些东西。数据库中的所有文件实际上都是 zip 文件本身,所以我试图压缩一堆 zip 文件。我认为这不会要求对它们进行不同于压缩任何其他格式的文件的处理。任何人都可以看到缺少什么吗?这是我在处理下载的 servlet 中的 doGet 方法代码。大部分代码是在 stackoverflow 上找到的。请注意,FileSubmitted 对象是我的 DOA,其中包含数据库中每个文件的所有文件信息,包括 Blob 本身:

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

【问题讨论】:

  • 请您扩展一下“用于压缩文件的代码卡住了一些东西” - 是否有错误,您是否添加了日志记录以查看发生了什么?您可以尝试通过将邮政编码从 servlet 中取出并在包含少量已知文件的 main 方法中运行来隔离问题。尝试使用命令行压缩相同的文件,看看时间是什么 - 也许你的文件很大,只是需要很长时间。
  • 对不起,我知道那是含糊的。 “有些东西卡住了”,我的意思是我没有收到任何错误,但是 zip 文件没有被发送到浏览器进行下载。我尝试在整个代码中放置 print 语句,以确保整个方法正在执行,而且看起来确实如此。它只是没有完成我想要的。我会尝试你的一些建议。谢谢。

标签: java jsp servlets zipoutputstream


【解决方案1】:

如果这对其他人有帮助,我找到了问题的答案。上面发布的代码实际上非常适合从数据库下载多个文件并创建一个 zip 文件供客户端下载。问题是我通过 ajax 调用 servlet,显然你不能通过 ajax 调用下载文件。所以我把我的jsp页面改成通过提交表单调用servlet,然后就完美的下载到浏览器了。

【讨论】:

    【解决方案2】:

    首先创建一个包含所有 zip 文件的 zip 文件。

    使用 ServletOutputStream 代替 ZipOutputStream

    然后使用下面的代码

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

    【讨论】:

    • 谢谢,我会试试这个 Kiran Jujare。你能告诉我 - 'final String filename = "/usr/local/FileName" + ".zip";' zip 文件的名称是否已经创建?你怎么知道扩展名是'/usr/local/FileName'?
    • 您必须创建要下载的 zip 文件,并将名称传递给 String filename
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    相关资源
    最近更新 更多