4

我有一些 Java 代码使用 servlet 和 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(stream) 看起来像:

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

谁能发现我做错了什么?

干杯,李

4

5 回答 5

4

我不喜欢的一件事是在 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 }

注意第 5 行的“else”,以及第 6 行的两个附加参数(数组索引起始位置和要复制的长度)。

我可以想象,对于较大的文件,如图像,缓冲区在填充之前返回(也许它正在等待更多)。这意味着您会无意中写入保留在缓冲区尾端的旧数据。这几乎肯定会在 EoF 的大部分时间发生,假设缓冲区 > 1 字节,但 EoF 的额外数据可能不是您损坏的原因......这是不可取的。

于 2008-09-03T17:49:35.350 回答
1

我只是使用commons io然后你可以做一个 IOUtils.copy(InputStream, OutputStream);

它还有许多其他有用的实用方法。

于 2008-09-03T20:13:20.123 回答
0

您确定图像没有出现乱码,或者您在进入的过程中没有丢弃一些数据包。

于 2008-09-03T13:45:49.883 回答
0

我不知道它有什么不同,但方法签名似乎不匹配。在您的getBytes()方法中调用的doPost()方法只有一个参数:

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

而您包含的方法源有两个参数:

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

希望有帮助。

于 2008-09-03T14:12:29.397 回答
0

您可以对原始文件和上传的文件执行校验和,看看是否有任何直接的差异?

如果有,那么您可以查看执行差异,以确定丢失的文件的确切部分已更改。

突然想到的事情是流的开始或结束,或字节序。

于 2008-09-03T14:13:46.553 回答