首页 > 代码库 > Spring 4 官方文档学习(十一)Web MVC 框架之multipart(文件上传)支持

Spring 4 官方文档学习(十一)Web MVC 框架之multipart(文件上传)支持

http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-multipart

 

1、简介

Spring内置的multipart支持会处理web应用中的文件上传。你可以启用该支持 -- 通过可插拔的MultipartResolver对象们,它们都是定义在 org.springframework.web.multipart 包中。Spring提供了一个MultipartResolver实现,配合Commons FileUpload使用,或者配合Servlet 3.0 multipart 请求解析使用。

 

默认,Spring不会处理multipart,因为一些开发者希望由自己来处理它们。你可以让Spring来处理 -- 通过在web应用的context中添加一个multipart resolver。每个请求都会被检查,以查看其是否包含一个multipart。如果没有,就放行。如果有,在你的上下文中声明的MultipartResolver会被用来处理它。之后,你就可以像对待其他attribute一样来对待在你请求中的multipart attribute。

 

2、结合Commons FileUpload来使用MultipartResolver

下例示意了如何使用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>

当然,你还要将需要的jars放到你的classpath内,这样才能使其正常工作。在该例中,你需要使用 commons-fileupload.jar 。

 

当Spring DispatcherServlet 探测到一个multi-part请求时,它会激活已声明的resolver,并将请求交给它。该resolver会将当前的HttpServletRequest封装进一个MultipartHttpServletRequest,后者支持multipart file uploads。通过使用MultipartHttpServletRequest,你可以在controllers中获取包含在该请求中的multiparts的信息,还可以实际访问到这些multipart files。

 

3、结合Servlet 3.0 来使用MultipartResolver

为了使用基于Servlet 3.0 的multipart解析,你需要给DispatcherServlet标记一个”multipart-config”部分 -- 在xml中,或者,在编码式Servlet注册中标记一个javax.servlet.MultipartConfigElement,或者,在自定义Servlet class情况下,使用javax.servlet.annotation.MultipartConfig注解。 配置设置,例如最大尺寸或者存储位置,需要在该Servlet注册级别上应用,因为Servlet 3.0 不允许这些设置由MultipartResolver来完成!

 

一旦Servlet 3.0 multipart解析被启用了,你就可以将StandardServletMultipartResolver添加到你的Spring配置中:

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

 

4、处理form中的文件上传

首先,创建一个form带有file input,允许用户上传。encoding attribute (enctype=”multipart/form-data”)会告诉浏览器将forms以multipart 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 {

    @PostMapping("/form")
    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元素。在该例中,没有涉及byte[],但你仍然可以将其保存到数据库、文件系统等等。

 

当使用Servlet 3.0 multipart 解析时,你还可以使用javax.servlet.http.Part:

@Controller
public class FileUploadController {

    @PostMapping("/form")
    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、处理来自编码式客户端的文件上传请求

multipart请求还可以来自非浏览器的客户端 -- 在REST风格式服务场景中。所有上述例子和配置均适用于这种情况。 然而,不同于浏览器,编码式客户端也可以发送特定内容类型的更加复杂的数据 -- 例如,一个multipart请求带有一个文件和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 来访问 "meta-data"部分。然而,你可能倾向于接收一个强类型的对象 -- 由请求中的JSON格式数据初始化而成的,非常类似于@RequestBody使用HttpMessageConverter将一个non-multipart请求的请求体转成目标对象。

 

此时,你可以使用@RequestPart注解来代替@RequestParam注解。它允许你再来关注一个经过HttpMessageConverter的特定的multipart内容其‘Content-Type‘ header部分。

@PostMapping("/someUrl")
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 4 官方文档学习(十一)Web MVC 框架之multipart(文件上传)支持