开发者

Java servlet: problem with corrupt file download

开发者 https://www.devze.com 2023-01-18 12:02 出处:网络
I use three servlets to serve files for download: ByteArrayDownloadServlet: used for small files, such as reports or files from database

I use three servlets to serve files for download:

  • ByteArrayDownloadServlet: used for small files, such as reports or files from database
  • FileDownloadServlet: used for small to large files
  • MultipleFileDownloadServlet: create a zip with the requested files and stream it

They are based in the following implementation: link text

I have received several complaints about corrupted downloads. The problem is that I can't simulate or find a pattern in the errors:

  • sometimes with large files
  • sometimes when the user requests more than one file to download and a zip file and is created dynamically
  • sometimes with smaller files, but that are being requested by many users simultaneously

In the post's mentioned above comments there are people reporting similar problems, but no solution. I also read a lot of threads from here and this the closer I got: link text

Has anyone went through similar problem or have some sample code that works?

Thanks, Felipe

@Override
@SuppressWarnings("unchecked")    
protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws Serv开发者_StackOverflow中文版letException, IOException
{
    HttpSession session = request.getSession();
    List<File> selectedFileList = (List<File>) session.getAttribute("selectedFileList");

    if(selectedFileList == null)
    {
        response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED, "Lista de arquivos não informada");
        return;
    }

    response.reset();
    response.setContentType("application/zip");        

    response.setHeader("Content-Disposition", "attachment; filename=\""
        + "atualizacoes_"
        + new Date().getTime() + ".zip" + "\"");

    ZipOutputStream output = null;

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

        for(File file : selectedFileList)
        {
            InputStream input = new FileInputStream(file);
            output.putNextEntry(new ZipEntry(file.getName()));                

            byte[] buffer = new byte[DownloadHandler.DEFAULT_BUFFER_SIZE];
            int length;
            while((length = input.read(buffer)) > 0)
            {
                output.write(buffer, 0, length);
            }

            output.closeEntry();
            input.close();
        }            

     output.finish();
     output.flush();
     output.close();
  }
  catch(Exception e) 
  {
      if(!(e instanceof ClientAbortException))
      {
          new ExceptionMail(getClass().getSimpleName(), e);
      }
    }
  finally
  {            
        session.removeAttribute("selectedFileList");        
  }


The most common causes for randomly corrupted downloads from a servlet is that the servlet is not threadsafe and/or that it is reading bytes as characters. Sharing request or session based data among requests in the same session or servletcontext is also a possible cause for this problem.


You should not close the outputstream as it is managed by the servlet container. I'm not sure about the flush.


You have a serious flow in your code in below lines.

int length;
        while((length = input.read(buffer)) > 0)
        {
            output.write(buffer, 0, length);
        }

Your 'input' is a FileInputStream right? How can you make sure the FileInputStream has always more than 0 bytes available throughout your iteration? Instead above it must be written as below.

int length;
        while((length = input.read(buffer)) != -1)
        {
            output.write(buffer, 0, length);
        }
0

精彩评论

暂无评论...
验证码 换一张
取 消