Pergunta

Eu tenho algum código Java usando um servlet e Apache Commons FileUpload para fazer upload de um arquivo para um diretório definido.Está funcionando bem para dados de caracteres (por exemploarquivos de texto), mas os arquivos de imagem estão distorcidos.Posso abri-los, mas a imagem não parece como deveria.Aqui está meu código:

Servlets

protected void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
    try {
      String customerPath = "\\leetest\\";

      // Check that we have a file upload request
      boolean isMultipart = ServletFileUpload.isMultipartContent(request);

      if (isMultipart) {
        // Create a new file upload handler
        ServletFileUpload upload = new ServletFileUpload();

        // Parse the request
        FileItemIterator iter = upload.getItemIterator(request);
        while (iter.hasNext()) {
          FileItemStream item = iter.next();
          String name = item.getFieldName();
          if (item.isFormField()) {
            // Form field.  Ignore for now
          } else {
            BufferedInputStream stream = new BufferedInputStream(item
                .openStream());
            if (stream == null) {
              LOGGER
                  .error("Something went wrong with fetching the stream for field "
                      + name);
            }

            byte[] bytes = StreamUtils.getBytes(stream);
            FileManager.createFile(customerPath, item.getName(), bytes);

            stream.close();
          }
        }
      }
    } catch (Exception e) {
      throw new UploadException("An error occured during upload: "
          + e.getMessage());
    }
}

StreamUtils.getBytes(stream) se parece com:

public static byte[] getBytes(InputStream src, int buffsize)
      throws IOException {
    ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
    byte[] buff = new byte[buffsize];
    while (true) {
      int nBytesRead = src.read(buff);
      if (nBytesRead < 0) {
        break;
      }
      byteStream.write(buff);
    }

    byte[] result = byteStream.toByteArray();
    byteStream.close();

    return result;
}

E finalmente FileManager.createFile se parece com:

public static void createFile(String customerPath, String filename,
      byte[] fileData) throws IOException {
    customerPath = getFullPath(customerPath + filename);
    File newFile = new File(customerPath);
    if (!newFile.getParentFile().exists()) {
      newFile.getParentFile().mkdirs();
    }

    FileOutputStream outputStream = new FileOutputStream(newFile);
    outputStream.write(fileData);
    outputStream.close();
  }

Alguém pode identificar o que estou fazendo de errado?

Saúde, Lee

Foi útil?

Solução

Uma coisa que não gosto está aqui neste bloco de StreamUtils.getBytes():

 1 while (true) {
 2   int nBytesRead = src.read(buff);
 3   if (nBytesRead < 0) {
 4     break;
 5   }
 6   byteStream.write(buff);
 7 }

Na linha 6, ele grava todo o buffer, não importa quantos bytes sejam lidos.Não estou convencido de que este será sempre o caso.Seria mais correto assim:

 1 while (true) {
 2   int nBytesRead = src.read(buff);
 3   if (nBytesRead < 0) {
 4     break;
 5   } else {
 6     byteStream.write(buff, 0, nBytesRead);
 7   }
 8 }

Observe o 'else' na linha 5, junto com os dois parâmetros adicionais (posição inicial do índice da matriz e comprimento a ser copiado) na linha 6.

Eu poderia imaginar que para arquivos maiores, como imagens, o buffer retorna antes de ser preenchido (talvez esteja esperando por mais).Isso significa que você estaria gravando involuntariamente dados antigos que restavam no final do buffer.É quase certo que isso está acontecendo na maioria das vezes no EoF, assumindo um buffer> 1 byte, mas dados extras no EoF provavelmente não são a causa da sua corrupção... simplesmente não são desejáveis.

Outras dicas

eu apenas usaria comum io Então você poderia simplesmente fazer um IOUtils.copy(InputStream, OutputStream);

Possui muitos outros métodos utilitários úteis.

Você tem certeza de que a imagem não está distorcida ou que você não está deixando cair alguns pacotes no caminho?

Não sei que diferença isso faz, mas parece haver uma incompatibilidade nas assinaturas dos métodos.O getBytes() método chamado em seu doPost() método tem apenas um argumento:

byte[] bytes = StreamUtils.getBytes(stream);

enquanto a fonte do método que você incluiu tem dois argumentos:

public static byte[] getBytes(InputStream src, int buffsize)

Espero que ajude.

Você pode realizar uma soma de verificação no arquivo original e no arquivo enviado e ver se há alguma diferença imediata?

Se houver, você pode executar uma comparação para determinar as partes exatas do arquivo que estão faltando alteradas.

As coisas que vêm à mente são o início ou o fim do fluxo, ou o fim.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top