5

有没有人知道任何产品或库,如 Apache Commons FileUpload 将处理 PUT 文件上传?

任何友好的建议或指导将不胜感激!

全文:

我们开始为我们的 java webapp 实现文件上传 rest(like) 服务,但似乎没有任何“简单”的解决方案可以通过 HTTP PUT 方法处理文件上传。

我们希望找到像Apache Commons FileUpload项目这样的库,但它不仅仅处理“HTML 中基于表单的文件上传”和/或“multipart/form-data”。

我们非常喜欢 FileUpload 能够临时存储文件、在被询问时移动这些文件,然后在不再使用临时文件后清理它们。我们还喜欢 Spring 会自动将 MultipartFile List 绑定到我们的命令对象的事实,并且当它进入我们其他基于 html 表单的文件上传控制器时,我们可以使用它。

全栈背景:

  • Spring MVC (3.2.3.RELEASE)
  • 雄猫 7
  • 我们正在尝试遵循分层架构(UI、服务/业务逻辑、持久性)

感谢您的时间!


以下 url 是一个示例,显示了从请求的 InputStream 上传文件的能力。代码完成了工作,但它的生产质量并不高。

https://boplicity.nl/confluence/display/spring/Using+HTTP+PUT+and+Spring+MVC+to+upload+files


我们正在使用以下 curl 命令来测试我们的 web 服务:

curl -v -k -X PUT --data-binary @"c:/java/files/tempfilename.txt" https://localhost:8443/api/file/tempfilename.txt

xwoker 然后给出了以下漂亮的 curl 示例:

curl -v -X PUT -T "myfile" http://localhost:8080/mytargetfilename
4

2 回答 2

10

让 spring 正确响应 HTTP PUT 方法的文件上传请求是相当轻松的。

只需在自定义的MultipartResolver类中覆盖isMultipart()方法即可。

import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.servlet.ServletRequestContext;

import javax.servlet.http.HttpServletRequest;

public class PostAndPutCommonsMultipartResolver extends CommonsMultipartResolver {

    private static final String POST_METHOD = "POST";
    private static final String PUT_METHOD = "PUT";

    @Override
    public boolean isMultipart(HttpServletRequest request) {

        boolean isMultipartRequest = false;

        if (request != null) {

            if (POST_METHOD.equalsIgnoreCase(request.getMethod()) || PUT_METHOD.equalsIgnoreCase(request.getMethod())) {

                isMultipartRequest = FileUploadBase.isMultipartContent(new ServletRequestContext(request));
            }
        }

        return isMultipartRequest;
    }
}

真正重要的是扩展了默认的MultipartResolver以便isMultipart()方法将为 POST 或 PUT 请求返回 true。

一般来说,有两个默认的 MultipartResolver 实现: CommonsMultipartResolver(与 Apache Commons FileUpload 一起使用)和StandardServletMultipartResolver(与 Servlet 3.0+ Part API 一起使用)。

由于我们使用的是Apache Commons FileUpload,我们扩展了 CommonsMultipartResolver 类。

MultipartResolver 的 Javadoc页面上的文档解释了如何为您的应用程序正确定义自定义的 MultipartResolver(强调添加):

Spring DispatcherServlets 没有使用默认的解析器实现,因为应用程序可能会选择自己解析其多部分请求。要定义实现,请在 DispatcherServlet 的应用程序上下文中创建一个 id 为“multipartResolver”的 bean。这样的解析器将应用于该 DispatcherServlet 处理的所有请求。

对于 xml 配置的应用程序,它看起来类似于以下内容:

<bean id="multipartResolver" class="<package>.<name>.PostAndPutCommonsMultipartResolver"/>

对于注释配置的应用程序,它将看起来接近以下内容:

@Bean(name = "multipartResolver")
public CommonsMultipartResolver createMultipartResolver() {
    return new PostAndPutCommonsMultipartResolver();
}

有关 MultipartResolver 的注释配置的更多信息

于 2013-09-24T20:49:28.383 回答
1

我不知道有任何库可以满足您的要求。但是,如果您不介意进行一些编码,我认为创建类似内容的好方法是编写自己的

public class FileMessageConverter extends AbstractHttpMessageConverter<File> 

将请求正文转换为 tmp 目录中的文件:

@Override
protected File readInternal(Class<? extends File> clazz, HttpInputMessage inputMessage)
        throws IOException, HttpMessageNotReadableException {

    InputStream inputStream = inputMessage.getBody();
    File tmpFile = File.createTempFile("upload","tmp");
    if (inputStream != null) {
        FileOutputStream outputStream = new FileOutputStream(tmpFile);

        byte[] buffer = new byte[1024];
        int bytesRead;

        while ((bytesRead = inputStream.read(buffer)) > 0) {
            outputStream.write(buffer, 0, bytesRead);
        }

        outputStream.flush();

        outputStream.close();
    }
    return tmpFile;
}

在控制器中,您将定义您的方法:

@RequestMapping(value="/{fileName}", method = RequestMethod.PUT)
public ResponseEntity uploadFile(@PathVariable(value="fileName") String fileName, @RequestBody File tmpFile) throws IOException {

    // .. process tmpFile, e.g. tmpFile.renameTo(new File(fileName);
    return new ResponseEntity<String>(HttpStatus.CREATED);
}

不要忘记注册您的 FileMessageConverter,例如

@Configuration
@EnableWebMvc
@ComponentScan(basePackages =  {"my.controller.package"})
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(new FileMessageConverter());
    }
}

调用上传的 curl 命令:

curl -v -X PUT -T "myfile" http://localhost:8080/mytargetfilename
于 2013-09-18T13:12:27.773 回答