2013-09-10 129 views
4

有没有人有任何产品或库像Apache Commons FileUpload处理PUT文件上传?通过HTTP上传文件上传PUT请求

任何友好的建议或方向将非常感激!

全文:

我们开始实现文件上传休息(等)的服务,为我们的Java web应用程序,但似乎没有任何可以“轻松”解决方案通过使用HTTP文件上传处理PUT方法。

我们希望找到一个像Apache Commons FileUpload这样的项目,但不仅仅是处理“HTML格式的文件上传”和/或“multipart/form-data”。

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

全栈背景:

  • 的Spring MVC(3.2.3.RELEASE)
  • 的Tomcat 7
  • 我们正在试图按照分层架构(UI,服务/业务逻辑,持久性)

谢谢你的时间!


下面的网址是显示从请求的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 -v -X PUT -T "myfile" http://localhost:8080/mytargetfilename 
+0

找到原始代码: https://boplicity.nl/confluence/display/spring/Using+HTTP+PUT+and+Spring+MVC+to+upload+files – hooknc

+0

不应该使用路径变量fileName某处? – xwoker

+0

@xwoker,是的,我们应该在某处使用fileName,但这不是我的文章的要点。我会尝试用更好的代码示例来更新我的问题,解释我们试图实现的简单性。 – hooknc

回答

7

这是很容易得到的弹簧正确为PUT方法一个HTTP文件上传请求。

只需要在定制的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请求。

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

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

还有就是MultipartResolver's Javadoc页面,介绍了如何正确定义一个定制的MultipartResolver为您的应用程序(重点是我的)的文档:

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

一个XML配置的应用程序它会寻找接近以下几点:

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

对于注解配置的应用程序它会寻找接近以下几点:

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

More information on Annotation configuration of MultipartResolver

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 
+0

不错。我还没有想过使用MessageConverter,这个好主意!我知道实际上有一个野外图书馆很可能不会发生,我们已经解决了我们将不得不编写一些代码。问题是,在这种情况下你将如何清理临时文件? – hooknc

+0

我不认为你可以保证提前清理。但是你可能想看看Apache Axis如何实现他们的TempFileManager。或者甚至用它来代替File.createTempFile https://svn.apache.org/repos/asf/axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/deployment/util/TempFileManager的.java – xwoker