14、Spring MVC 之 multipart (file upload) support

来源:互联网 发布:上海华云数据 知乎 编辑:程序博客网 时间:2024/05/20 17:23

1、Introduction

Spring在web应用程序的内置支持处理multipart文件上传.你可以使用定义在org.springframework.web.multipart包里面的MultipartResolver对象可插拔的支持处理multipart文件上传。Spring提供了一个是基于Commons FileUploadMultipartResolver实现使用,另一个是基于Servlet 3.0的multipart语法解析。

默认情况下Spring不支持multipart处理,因为一些开发者想自己处理multiparts.你可以在web应用context中添加multipart解析器来使用Spring的multipart处理。每个request都会被检测它是否是一个multipart.如果没有检测到multipart,request会按照预期要求继续。如果在request检测到multipart并且在你的context中声明了使用MultipartResolver。之后,在你请求的multipart将会和其他属性一样对待。

2、Using a MultipartResolver with Commons FileUpload

下面的例子是展现如何使用CommonsMultipartResolver:

<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放在你的classpath中使得multipart解析器能够工作.在使用CommonsMultipartResolver这种情况下,你需要使用commons-fileupload.jar

当Spring MVC的DispatcherServlet检测到一个multi-part类型的request,它会激活你context中声明的解析器来处理这个request。这个解析器会包装当前HttpServletRequestMultipartHttpServletRequest对象中,因为这个对象支持multipart类型的文件上传。使用MultipartHttpServletRequest,你可以获取到这个request中包含的multparts信息然后在你的Controller中操作multiparts类型的文件。

3、Using a MultipartResolver with Servlet 3.0

为了能够使用基于Servlet 3.0的multipart解析,你需要在web.xml通过"multipart-config" section来标记DispatcherServlet,或者使用Servlet编程式注册一个javax.servlet.MultipartConfigElement,或者通过使用javax.servlet.annotation.MultipartConfig注解来定制化你的Servlet class.在配置中可以配置maximum sizes或者存储地点但是需要Servlet 3.0,以上配置的属性不能够在MultipartResolver中配置。

在上文中其中一种方法就提及到使用Servlet 3.0 multipart解析。你可以添加StandardServletMultipartResolver到你的Spring配置文件中:

<bean id="multipartResolver"        class="org.springframework.web.multipart.support.StandardServletMultipartResolver"></bean>

4、Handling a file upload in a form

MultipartResolver完成了工作后,请求的处理过程像任何其他一样。首先创建一个带file类型的input框form表单,允许用户上传。这个表单的encoding属性设置为 ( enctype="multipart/form-data")让浏览器知道以multipart请求来编码这个表单。

<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来处理文件upload. 这个Controller与一个带@Controller注解的类类似,除了我们需要在方法参数中使用MultipartHttpServletRequest或者MultipartFile

@Controllerpublic class FileUploadController {    @RequestMapping(path = "/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";    }}

注意:标注@RequestParam方法参数是映射form表单中input声明elements。在这个例子中,没有对byte[]进行任何操作,但是在实践中你可以把它保存在database中,或者储存在文件系统中等等。

当使用Servlet 3.0 multipart解析的时候,你也可以使用javax.servlet.http.Part做为方法参数。

@Controllerpublic class FileUploadController {    @RequestMapping(path = "/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";    }}

5、Handling a file upload request from programmatic clients

multipart请求还可以在一个restful服务的场景从非浏览器提交客户端提交。所有上面的例子与配置同样适用。但是与浏览器典型的表单域提交文件不一样的是,编程式客户端同样可以发送指定复杂的content类型的数据 – 例如,一个一部分是file和另一部分是JSON格式数据的multipart请求:

POST /someUrlContent-Type: multipart/mixed--edt7Tfrdusa7r3lNQc79vXuhIIMlatb7PQg7VpContent-Disposition: form-data; name="meta-data"Content-Type: application/json; charset=UTF-8Content-Transfer-Encoding: 8bit{    "name": "value"}--edt7Tfrdusa7r3lNQc79vXuhIIMlatb7PQg7VpContent-Disposition: form-data; name="file-data"; filename="file.properties"Content-Type: text/xmlContent-Transfer-Encoding: 8bit... File Data ...

你可以使用在controller方法参数中使用@RequestParam("meta-data") String metadata来使用命名为”meta-data”的部分。但是你可能会更喜欢用强类型对象来初始化使用request的part中body里的JSON格式的数据。与@RequestBody转换request中的body的非multipart类型成目标对象方法类似,可以使用HttpMessageConverter

在这种情况下你可以使用@RequestPart注解代替@RequestParam注解。它可以让你有一个特定的内容multipart通过一个HttpMessageConverter考虑multipart的内容类型的头'Content-Type':

@RequestMapping(path = "/someUrl", method = RequestMethod.POST)public String onSubmit(@RequestPart("meta-data") MetaData metadata,        @RequestPart("file-data") MultipartFile file) {    // ...}

注意:MultipartFile类型的方法参数可以使用@RequestParam或者@RequestPart。但是@RequestPart("meta-data") MetaData方法参数仅仅适用于基于'Content-Type'header的JSON内容的读取并且通过MappingJackson2HttpMessageConverter来进行转换。

因为水平有限,翻译不足之处还望见谅。
原文地址:spring-framework-reference-4.2.6.RELEASE

0 0
原创粉丝点击