【问题标题】:Java: Binary File Upload using Restlet + Apache Commons FileUploadJava:使用 Restlet + Apache Commons FileUpload 上传二进制文件
【发布时间】:2015-02-04 18:31:46
【问题描述】:

我有一个带有 Restlet 2.3 的 REST API,需要对其实现文件上传功能。 问题是,当有人使用 POST(使用 multipart/form-data Content-Type)上传文件时,文件会以另一种编码方式到达服务器。 为了测试这一点,我在 Unix 终端中打印了原始文件的内容,然后在使用 Apache Commons FileUpload 解析请求之前再次打印它(使用与此示例几乎相同的代码 http://restlet.com/technical-resources/restlet-framework/guide/2.2/extensions/fileupload)。两个打印的内容非常相似,但是原始文件的字符较少,所以我假设我的 Java 服务器使用错误的编码来解释文件。

我发送的文件是 PNG 图像。使用文本文件,服务器可以完美运行,但是当我发送照片或任何二进制文件时,就会出现问题。

【问题讨论】:

标签: java file upload apache-commons restlet


【解决方案1】:

我不知道您是如何检查收到的内容的。首先,您应该在多部分请求的内容中检查用于文件部分的内容类型。对于 JPG 图像,您应该有类似的东西:

-----------------------------75956101888331271337088331
Content-Disposition: form-data; name="fileToUpload"; filename="myimage.jpg" 
Content-Type: image/jpeg

其次,我不知道您实际上是如何编写收到的内容的。 Apache Commons IO 带来了一个实用方法IOUtils.copy,它提供了一个简单的解决方案,可以将接收自InputStream 的内容写入OutputStream。查看如何在您的上下文中使用 ti:

while (fileIterator.hasNext()) {
    FileItemStream fi = fileIterator.next();
    if (fi.getFieldName().equals("fileToUpload")) {
        FileOutputStream fos = new FileOutputStream(
              "output"+File.separator+fi.getFieldName());
        IOUtils.copy(fi.openStream(), fos);
        fos.close();
    }
}

IMO,编码方面仅适用于文本而不适用于二进制内容。

希望对你有帮助, 蒂埃里

【讨论】:

  • 感谢您的回答,但我使用 Google 的 ByteStreams 类解决了它。
【解决方案2】:

我实际上是通过使用 Google 的 ByteStreams 类解决了这个问题:

while (fileIterator.hasNext()) {
    FileItemStream fi = fileIterator.next();
    if (fi.getFieldName().equals(FILE_TO_UPLOAD)) {
        byte[] byteArray = ByteStreams.toByteArray(fi.openStream());
        result = new String(byteArray,Charset.forName("ISO-8859-1"));
    }
}

【讨论】:

    【解决方案3】:

    我在上传图像文件时遇到了类似的问题。这就是我修复的方式。就我而言,问题是从输入流中读取的数据。由于它是从套接字读取的,因此不能保证您将填充数组的完整缓冲区。因此,您应该在将数据写入输出缓冲区/文件之前检查数据大小。这是我的代码,希望对您有所帮助。也可在存储库https://github.com/esabilbulbul/java-servlet-fileupload/blob/master/README.md

    // Create a new file upload handler
    ServletFileUpload upload = new ServletFileUpload();
    upload.setHeaderEncoding("UTF-8");
    
    // Parse the request
    FileItemIterator iter = upload.getItemIterator(request);
    while (iter.hasNext()) 
    {
        FileItemStream item = iter.next();
        String name = item.getFieldName();
    
        //InputStream attachmentStream = item.openStream();
        //byte[] attachmentBytes = ByteStreams.toByteArray(attachmentStream);
    
    
        //InputStream stream = item.getInputStream();
        InputStream stream = item.openStream();
    
        if (item.isFormField()) 
        {
            //System.out.println("Form field " + name + " with value " + Streams.asString(stream) + " detected.");
        }
        else
        {
            System.out.println("File field " + name + " with file name "+ item.getName() + " detected.");
    
            // Process the input stream
            FileOutputStream fout= new FileOutputStream ("c:\\" + item.getName());
            BufferedOutputStream bout= new BufferedOutputStream (fout);
            BufferedInputStream bin= new BufferedInputStream(stream);
            byte buf[] = new byte[2048];
            int len=0;
            while ((len = bin.read(buf)) > 0)//((bin.read(buf)) != -1)
            {
                bout.write(buf, 0, len);
                if (len<2048)
                    len = len;
            }
            bout.close();
            bin.close();
        }        
    }
    

    【讨论】: