在web应用中,spring内置对文件上传的支持。通过配置org.springframework.web.multipart.MultipartResolver来实现多媒体支持。spring提供一个基于Commons FileUpload的和一个基于Servlet3.0多媒体解析的MulipartResolver的实现。
默认情况下,spring没有多媒体处理,因为许多开发者需要自己处理多媒体。可以通过在web应用上下文中添加多媒体解析器来开启spring多媒体处理。每个request都会检查是否包含多媒体信息。如果在request中发现multipart,MultipartResolver就会被调用。之后,request中多媒体属性跟其他属性一样看待。
1.1 基于Commons FileUpload的MultipartResolver
例子:
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- one of the properties available; the maximum file size in bytes --> <property name="maxUploadSize" value="100000"/> </bean>
需要导入合适的jar包。CommonsMultipartResolver需要使用commons-fileupload.jar。
当spring DispatcherServlet检查request中的multi-part是,应用context中配置的解析器就会被激活。解析器将当前的HttpServletRequest包装成一个MultipartHttpServletRequest来支持多媒体文件上传,然后在controllers中就可以获取包含在request中的多媒体信息,或者访问它们。
1.2 基于Servlet3.0 的MultipartResolver
为了使用Servlet3.0的多媒体解析,需要在web.xml中将DispactcherServlet标记为“multipart-config”。或者在Servlet程序中使用javax.servlet.MultipartConfigElement注册。或者使用javax.servlet.annotation.MultipartConfig注解Servlet类。最大size和存储位置的配置需要在Servlet注册级别上应用,不允许从MultipartResolver中设置。
一旦Servlet3.0多媒体解析使用以上三种方法的一种,就可以在Spring configuration中配置StandardServletMultipartResolver:
<bean id="multipartResolver" class="org.springframework.web.multipart.support.StandardServletMultipartResolver"> </bean>
11.3 在form中处理文件上传
当MultipartResolver完成这些工作后,request就可以像其他的一样处理。首先,创建一个form用来上传文件,将enctype="multipart/form-data"属性设置,让浏览器知道怎么编码mulitpart request。
<html> <head> <title>Upload a file please</title> </head> <body> <h1>Please upload a file</h1> <form method="post" action="/form" enctype="multipart/form-data"> <input type="text" name="name"/> <input type="file" name="file"/> <input type="submit"/> </form> </body> </html>
下一步创建一个Controller来处理文件上传。例如:
@Controller public class FileUploadController { @RequestMapping(value = "/form", method = RequestMethod.POST) public String handleFormUpload(@RequestParam("name") String name, @RequestParam("file") MultipartFile file) { if (!file.isEmpty()) { byte[] bytes = file.getBytes(); // store the bytes somewhere return "redirect:uploadSuccess"; } return "redirect:uploadFailure"; } }
当使用Servlet3.0多媒体转化时可以使用javax.servlet.http.Part作为方法参数:
@Controller public class FileUploadController { @RequestMapping(value = "/form", method = RequestMethod.POST) public String handleFormUpload(@RequestParam("name") String name, @RequestParam("file") Part file) { InputStream inputStream = file.getInputStream(); // store bytes from uploaded file somewhere return "redirect:uploadSuccess"; } }
11.4处理来自编程客户端的文件上传request。
Multipart Request也许来自非浏览器客户端在RESTful服务场景。上面的例子和配置照常。然而不像浏览器那样典型的提交文件和简单的form域,编程客户端能发送许多指定content type的复杂的数据-例如多媒体request有一个文件以及JSON格式的数据:
POST /someUrl
Content-Type: multipart/mixed
--edt7Tfrdusa7r3lNQc79vXuhIIMlatb7PQg7Vp
Content-Disposition: form-data; name="meta-data"
Content-Type: application/json; charset=UTF-8
Content-Transfer-Encoding: 8bit
{
"name": "value"
}
--edt7Tfrdusa7r3lNQc79vXuhIIMlatb7PQg7Vp
Content-Disposition: form-data; name="file-data"; filename="file.properties"
Content-Type: text/xml
Content-Transfer-Encoding: 8bit
... File Data ...
可以通过@RequestParam("meta-data") String metadata来访问这部分参数。然而,你也许需要接受一个强类型对象从request body中的JSON格式数据中初始化出。类似于通过@RequestBody转化非多媒体request body中的目标对象使用HttpMessageConverter。
可以通过@RequestPart注解替代@RequestParma,其允许通过考虑multipart request header 中的‘Content-Type’,来转化。
@RequestMapping(value="/someUrl", method = RequestMethod.POST) public String onSubmit(@RequestPart("meta-data") MetaData metadata, @RequestPart("file-data") MultipartFile file) { // ... }
注意,MultipartFile访问可以用@RequestParam和@RequestPart互换。然而@RequestPart("meta-data") MetaData参数在这种情况下读取JSON内容基于其‘Content-Type’头,通过MappingJackson2HttpMessageConverter转化。