Java сервлет: проблема с загрузкой поврежденного файла - PullRequest
0 голосов
/ 04 октября 2010

Я использую три сервлета для обслуживания файлов для скачивания:

  • ByteArrayDownloadServlet: используется для небольших файлов, таких как отчеты или файлы из базы данных
  • FileDownloadServlet: используется для маленьких и больших файлов
  • MultipleFileDownloadServlet: создайте zip-файл с запрошенными файлами и передайте его

Они основаны на следующей реализации: текст ссылки

Я получил несколько жалоб на испорченные загрузки. Проблема в том, что я не могу смоделировать или найти шаблон в ошибках:

  • иногда с большими файлами
  • иногда, когда пользователь запрашивает более одного файла для загрузки и zip-файл и создается динамически
  • иногда с небольшими файлами, но они запрашиваются многими пользователями одновременно

В вышеупомянутых комментариях к посту есть люди, сообщающие о похожих проблемах, но не имеющие решения. Я также прочитал много тем отсюда, и это ближе, я получил: текст ссылки

Кто-нибудь сталкивался с подобной проблемой или есть пример кода, который работает?

Спасибо, Фелипе

@Override
@SuppressWarnings("unchecked")    
protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, 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");        
  }

Ответы [ 3 ]

2 голосов
/ 06 октября 2010

Наиболее распространенные причины случайного повреждения загрузок из сервлета заключаются в том, что сервлет не является потокобезопасным и / или что он читает байты как символы.Совместное использование запроса или данных на основе сеанса между запросами в том же сеансе или контекста сервлета также является возможной причиной этой проблемы.

0 голосов
/ 02 сентября 2013

У вас серьезный поток в вашем коде в следующих строках.

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

Ваш 'вход' является FileInputStream, верно?Как вы можете убедиться, что FileInputStream всегда имеет более 0 байтов, доступных на протяжении вашей итерации?Вместо этого выше должно быть написано как ниже.

int length;
        while((length = input.read(buffer)) != -1)
        {
            output.write(buffer, 0, length);
        }
0 голосов
/ 24 декабря 2012

Не следует закрывать выходной поток, поскольку он управляется контейнером сервлета. Я не уверен насчет флеша.

...