Вопрос

У меня есть некоторый Java-код, использующий сервлет и Apache Commons FileUpload для загрузки файла в заданный каталог.Он отлично работает для символьных данных (например,текстовые файлы), но файлы изображений получаются искаженными.Я могу открыть их, но изображение выглядит не так, как должно.Вот мой код:

Сервлет

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(поток) выглядит следующим образом:

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

И, наконец, FileManager.CreateFile выглядит следующим образом:

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();
  }

Кто-нибудь может определить, что я делаю не так?

Твое здоровье, Ли

Это было полезно?

Решение

Одна вещь, которая мне не нравится, находится здесь, в этом блоке из StreamUtils.getBytes():

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

В строке 6 он записывает весь буфер целиком, независимо от того, сколько байт было считано.Я не уверен, что так будет всегда.Правильнее было бы вот так:

 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 }

Обратите внимание на 'else' в строке 5, а также на два дополнительных параметра (начальная позиция индекса массива и длина для копирования) в строке 6.

Я мог бы представить, что для файлов большего размера, таких как изображения, буфер возвращается до того, как он будет заполнен (возможно, он ожидает большего).Это означает, что вы непреднамеренно записывали бы старые данные, которые оставались в хвостовой части буфера.Это почти наверняка происходит большую часть времени в EoF, предполагая, что буфер > 1 байт, но дополнительные данные в EoF, вероятно, не являются причиной вашего corruption...it, просто нежелательны.

Другие советы

Я бы просто использовал общий доступ io Тогда вы могли бы просто выполнить IOUtils.copy(InputStream, OutputStream);

В нем есть множество других полезных служебных методов.

Вы уверены, что изображение не получается искаженным или что вы не отбрасываете какие-то пакеты по пути?

Я не знаю, какая это имеет разница, но, похоже, имеет место несоответствие сигнатур методов.Тот Самый getBytes() метод, вызванный в вашем doPost() метод имеет только один аргумент:

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

в то время как источник метода, который вы включили, имеет два аргумента:

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

Надеюсь, это поможет.

Можете ли вы выполнить контрольную сумму для вашего исходного файла и загруженного файла и посмотреть, есть ли какие-либо непосредственные различия?

Если таковые имеются, вы можете посмотреть на выполнение diff, чтобы определить точные части файла, которые отсутствуют, изменены.

Вещи, которые приходят на ум, - это начало или конец потока, или порядковый номер.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top