`
小杨学JAVA
  • 浏览: 885824 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

在Spring MVC中使用FileUpload功能

 
阅读更多

  先让我们来看一段摘自《Spring 2.5 Reference 中文版》(http://www.redsaga.com/spring_ref/2.5/spring-reference.pdf)的一段关于FileUpload的开场描述: 

  "Spring支持web应用中的分段文件上传。这种支持是由即插即用的MultipartResolver来实现。这些解析器都定义在org.springframework.web.multipart包里。Sprig提供了现成的MultipartResolver可以支持Commons FileUpload(http://jakarta.apache.org/commons/fileupload)和COS FileUpload(http://www.servlets.ocm/cos)。" 

是的,Spring通过配置一个分段上传解析器来完成对文件上传的解析和封装工作,那么Spring是如何完成这一工作的呢: 

首先,DispatcherServlet必须找到一个文件上传解析器的实例,使用这个实例来检查本次请求的HttpServletRequest是否是一个分段文件上传的Request,通过下面的Spring 源码可以看到,首先必须保证有一个MultipartResolver的实例,并且由该类的Resolver的isMultipart方法来验证,本次Request是否为文件上传的Request.如果以上条件都满足,那么Spring将其转换为一个继承自HttpServletRequest的MultipartHttpServletRequest返回,这样在你的Controller中就可以使用这个经过转换的request,从中取到MultipartFile信息。 
Java代码  收藏代码
  1. protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException {  
  2.     if (this.multipartResolver != null && this.multipartResolver.isMultipart(request)) {  
  3.         if (request instanceof MultipartHttpServletRequest) {  
  4.             logger.debug("Request is already a MultipartHttpServletRequest - if not in a forward, " +  
  5.                     "this typically results from an additional MultipartFilter in web.xml");  
  6.         }  
  7.         else {  
  8.             return this.multipartResolver.resolveMultipart(request);  
  9.         }  
  10.     }  
  11.     // If not returned before: return original request.  
  12.     return request;  
  13. }  

由以上分析可以看出,我们必须配置一个MultipartResolver,在这里我们使用支持Commons FileUpload的CommonsMultipartResolver: 
Java代码  收藏代码
  1. <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" p:defaultEncoding="utf-8"/>  

而且我们可以在该Resolver中定义文件上传的最大长度: 
Java代码  收藏代码
  1. <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" p:defaultEncoding="utf-8" p:maxUploadSize="100000"/>  

当用户选择的上传文件大于maxUploadSize值的时候,commons fileupload会抛出一个异常MaxUploadSizeExceededException表示用户上传的文件超出了最大限制。 

当然,我们可以通过Spring MVC中的ExceptionResolver来针对该异常定义一个显示错误的View,但针对有可能存在的多个文件上传Controller中都会发生文件大小超长这个异常的情况,除了我们自定义一个粒度更细的ExceptionResolver,我们还可以把上传文件合法性判断挪到用户自己的Controller中来做。而且我个人更偏向于后一种做法。 

除了Spring Configuration之外,我们还需要准备一个页面上传的jsp文件供View视图使用: 
Java代码  收藏代码
  1. <%@ page language="java" contentType="text/html; charset=UTF-8"  
  2.     pageEncoding="UTF-8"%>  
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
  4.   
  5. <html>  
  6.     <head>  
  7.         <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
  8.         <title>Insert title here</title>  
  9.     </head>  
  10.       
  11.     <body style="text-align:left">  
  12.         <% if(request.getAttribute("success") != null) {%>  
  13.             Upload Successfully!!!<br/>  
  14.         <% }%>  
  15.         <form id="loginform" name="loginform" method="POST" enctype="multipart/form-data">  
  16.             <table width="100%" border="0" cellspacing="0" cellpadding="0">  
  17.                 <tr>  
  18.                     <td height="30" align="right">Choose File</td>  
  19.                     <td align="left">  
  20.                         <input name="imageFile" type="file"/>  
  21.                     </td>  
  22.                 </tr>  
  23.                 <tr>  
  24.                     <td align="center" colspan="2">  
  25.                         <input type="submit" value="submit" name="submit" />  
  26.                     </td>  
  27.                 </tr>  
  28.             </table>  
  29.         </form>  
  30.     </body>  
  31. </html>  

注意:在文件上传Form表单中,一定要将enctype设置为"multipart/form-data"因为只有这样才能使Spring知道这是一个文件上传的请求。 

细心的读者也许能发现Form表单中action为默认值也就是说post到和上传页面同样的URL,因此我们定义了一个Controller分别来处理这个请求的GET和POST请求。下面让我们来看看这个Controller: 

1.我们通过@Controller声明这个类为Spring组件,告知Spring容器在初始化的时候需要加载该类实例到Spring Context Container中。 
2.通过@RequestMapping("/sec_upload.do")将sec_upload.do的请求指向该Controller处理。 
Java代码  收藏代码
  1. @Controller  
  2. @RequestMapping("/sec_upload.do")  
  3. public class UploadController {  
  4.     //...  
  5. }  

3.定义一个处理GET请求的方法,该方法简单的将选择文件Form表单页展现给用户: 
Java代码  收藏代码
  1. @RequestMapping(method = RequestMethod.GET)  
  2.     public String handleUploadShow() {  
  3.         return "uploadView";  
  4.     }  

4.定义一个处理POST请求的方法,该方法进行用户文件上传处理: 
Java代码  收藏代码
  1. @RequestMapping(method = RequestMethod.POST)  
  2.     public String handleUploadProcess(  
  3.             @RequestParam("imageFile") MultipartFile file, Model model)  
  4.             throws Exception {  
  5.         //具体的业务逻辑操作。。。  
  6.         model.addAttribute("success""true");  
  7.         return "uploadView";  
  8.     }  

通过@RequestParam("imageFile")注解,Spring会将request请求中的imageFile的文件信息自动绑定到MultipartFile对象。 

上面的Controller方法解决的文件绑定的问题,但假设我们的Form表单中除了文件选择框还有其他一些用户填写的信息,那么我们怎么处理呢?仿照上面的方法,我们可以为多个参数提供多个@RequestParam注解来完成数据绑定工作,但我们也可以通过MultipartHttpServletRequest对象来获取这些信息,因为在DispatcherServlet中Spring已经将一个普通的HttpServletRequest转换为了一个MultipartHttpServletRequest: 
Java代码  收藏代码
  1. @RequestMapping(method = RequestMethod.POST)  
  2. public String handleAnotherUploadProcess(  
  3.         MultipartHttpServletRequest request, Model model) throws Exception {  
  4.     MultipartFile file = request.getFile("imageFile");  
  5.     //request.getParameter("xxx");  
  6.     //request.getContentType();  
  7.     //request.getContentLength();  
  8.     //some other processing...  
  9.     model.addAttribute("success""true");  
  10.     return "uploadView";  
  11. }  


这种方式还是需要我们不断的通过request.getParameter("xxx")方式来获得参数,了解Spring MVC的同学可能想到了,使用CommandObject绑定-回答正确。假设我们定义了一个POJO对象: 
Java代码  收藏代码
  1. public class BoUploadFile {  
  2.     private MultipartFile imageFile;  
  3.   
  4.     public MultipartFile getImageFile() {  
  5.         return imageFile;  
  6.     }  
  7.   
  8.     public void setImageFile(MultipartFile imageFile) {  
  9.         this.imageFile = imageFile;  
  10.     }  
  11.   
  12.     private String name;  
  13.   
  14.     public String getName() {  
  15.         return name;  
  16.     }  
  17.   
  18.     public void setName(String name) {  
  19.         this.name = name;  
  20.     }  
  21. }  

这个对象中不仅包括需要封装的上传文件信息,还包括其他一些用户输入的普通信息。那么有了这个封装对象,我们的Controller可以变成如下的样子: 
Java代码  收藏代码
  1. @RequestMapping(method = RequestMethod.POST)  
  2. public String handleThirdUploadProcess(BoUploadFile uploadFile, Model model) throws Exception{  
  3.     MultipartFile file = uploadFile.getImageFile();  
  4.     //这里你可以通过uploadFile.getName()...等等获取用户输入的其他普通信息了。  
  5.     model.addAttribute("success""true");  
  6.     return "uploadView";  
  7. }  


5.自定义一个文件验证类,来验证文件的合法性。 
Java代码  收藏代码
  1. /** 
  2.  * 用户文件上传验证类 
  3.  *  
  4.  * @author Jacky Lau created at 2008-8-27 
  5.  * @since 1.0 
  6.  * @version 1.0 
  7.  */  
  8. public class MultipartFileValidator {  
  9.   
  10.     private final static long MAX_SIZE = 1024 * 1024;  
  11.   
  12.     /** 
  13.      * 文件大小上限 
  14.      */  
  15.     private long maxSize = MAX_SIZE;  
  16.   
  17.     /** 
  18.      * 可接受的文件content-type 
  19.      */  
  20.     private String[] allowedContentTypes;  
  21.   
  22.     @PostConstruct  
  23.     public void afterPropertiesSet() {  
  24.         Assert  
  25.                 .notEmpty(allowedContentTypes,  
  26.                         "The content types allowed to be uploaded must contain one at least!");  
  27.     }  
  28.   
  29.     /** 
  30.      * 验证上传文件是否合法,如果不合法那么会抛出异常 
  31.      *  
  32.      * @param file 
  33.      *            用户上传的文件封装类 
  34.      */  
  35.     public void validate(MultipartFile file) {  
  36.         Assert.notNull(file, "The multipart file is null!");  
  37.         if (file.getSize() > maxSize)  
  38.             throw new FileOutOfMaxLengthException("error.upload.outmaxlen",  
  39.                     new Object[] { maxSize },  
  40.                     "The file uploaded is out of max file size!");  
  41.         if (!ArrayUtils.contains(allowedContentTypes, file.getContentType()))  
  42.             throw new ContentTypeNotSupportException("error.upload.content.notsupported"null,  
  43.                     "The content type '"+file .getContentType()+"' is not a valid content type !");  
  44.     }  
  45.   
  46.     /** 
  47.      * 设置文件上传大小上限 
  48.      *  
  49.      * @param maxSize 
  50.      *            文件上传大小上限 
  51.      */  
  52.     public void setMaxSize(long maxSize) {  
  53.         this.maxSize = maxSize;  
  54.     }  
  55.   
  56.     /** 
  57.      * 设置可接受的文件content-type数组 
  58.      *  
  59.      * @param allowedContentTypes 
  60.      *            可接受的文件content-type数组 
  61.      */  
  62.     public void setAllowedContentTypes(String[] allowedContentTypes) {  
  63.         this.allowedContentTypes = allowedContentTypes;  
  64.     }  
  65.   
  66. }  


这样我们可以通过这个validator判断上传的文件是否超出了最大限制,文件格式是否正确等判断。我们可以通过配置文件配置该验证器,在这里为了方便起见在类中我用以下方式来初始化该验证器: 
Java代码  收藏代码
  1. private MultipartFileValidator validator;  
  2.   
  3. @PostConstruct  
  4. public void init() {  
  5.     validator = new MultipartFileValidator();  
  6.     validator.setAllowedContentTypes(new String[] { "image/jpeg",  
  7.             "image/pjpeg" });  
  8. }  


至此,我们已经完成了文件上传的开发,可以看出这和普通的Controller开发没有任何区别,简单而且灵活。以下是该Controller的全部代码: 

Java代码  收藏代码
  1. @Controller  
  2. @RequestMapping("/sec_upload.do")  
  3. public class UploadController {  
  4.   
  5.     private MultipartFileValidator validator;  
  6.   
  7.     @PostConstruct  
  8.     public void init() {  
  9.         validator = new MultipartFileValidator();  
  10.         validator.setAllowedContentTypes(new String[] { "image/jpeg",  
  11.                 "image/pjpeg" });  
  12.     }  
  13.   
  14.     @RequestMapping(method = RequestMethod.GET)  
  15.     public String handleUploadShow() {  
  16.         return "uploadView";  
  17.     }  
  18.   
  19.     @RequestMapping(method = RequestMethod.POST)  
  20.     public String handleUploadProcess(  
  21.             @RequestParam("imageFile") MultipartFile file, Model model)  
  22.             throws Exception {  
  23.         validator.validate(file);  
  24.         String path = "d:\\temp\\ftp\\" + file.getOriginalFilename();  
  25.         String resizePath = "d:\\temp\\ftp\\resize\\"  
  26.                 + file.getOriginalFilename();  
  27.         FileHelper.save(path, file.getBytes());  
  28.         if (ImageHelper.isJpg(ImageHelper.getImageType(path)))  
  29.             ImageHelper.resizeJPG(path, resizePath, 120118);  
  30.         model.addAttribute("success""true");  
  31.         return "uploadView";  
  32.     }  
  33. }  

分享到:
评论

相关推荐

    spring mvc上传文件

    清晰的注释和简单明了的代码,绝对让你瞬间掌握如何使用ajax上传的的要领,实现举一反三

    spring mvc开发集合包

    初用spring mvc 找各种包用了不少时间,而且下载也比较慢,特将有可能用到的大部分包集合起来,大家可以根据需要选择。 包括:spring mvc 官方发布的所有包,版本3.1.0 另外还包括: aopalliance-1.0.jar aop支持包...

    spring mvc核心包(包含文件上传)

    spring mvc核心包,包含spring mvc文件上传所需的commons.fileupload和commons.io

    关于Spring MVC项目(maven)中通过fileupload上传文件

    NULL 博文链接:https://843977358.iteye.com/blog/2215988

    spring mvc+ajax 文件上传

    文件上传demo:前台ajax,后台spring mvc,效率好于传统表单上传。

    jQueryFileUploadMaster 插件 spring mvc简单整合

    jQueryFileUploadMaster 上传 插件 spring mvc 整合 兼容IE8/9(IE8下功能只能说能够使用,但是不能和chrome比,比如说:IE8下,一次只能上传一个文件,而chrome可以多个同时上传)

    利用 FormData 对象和 Spring MVC 配合实现Ajax文件下载功能

    利用 FormData 对象和 Spring MVC 配合可以实现Ajax文件上载功能: 步骤 1.导入组件并准备静态脚本 &lt;groupId&gt;commons-fileupload &lt;artifactId&gt;commons-fileupload &lt;version&gt;1.3.2 &lt;h1&gt;Ajax 文件上载 &lt;...

    Spring MVC文件上传与下载

    Spring MVC 框架的文件上传是基于 commons-fileupload 组件的文件上传,只不过 Spring MVC 框架在原有文件上传组件上做了进一步封装,简化了文件上传的代码实现,取消了不同上传组件上的编程差异。 commons-...

    Spring_MVC_051:Spring MVC 学习总结(五)——校验与文件上传

    Spring MVC 学习总结(五)——校验与文件上传 目录 2.2.7、范围 2.2.8、其它注解 2.3、注解控制器参数 1.4、在UI中添加错误标签 1.5、测试运行 三、使用jQuery扩展插件Validate实现前端校验 3.1、jQuery扩展插件...

    spring4.3.9相关jar包

    Spring 其它组件要都要使用到这个包里的类,是其它组件的基本核心,当然你也可以在自己的应用系统中使用这些工具类。 外部依赖Commons Logging, (Log4J)。 spring-beans.jar(必须):这 个jar 文件是所有应用都要...

    com.springsource.org.apache.commons.fileupload-1.2.0.jar

    spring mvc 上传需要的jar包 com.springsource.org.apache.commons.fileupload-1.2.0.jar com.springsource.org.apache.commons.io-1.4.0.jar

    spring springmvc mybatis 整合jar包

    spring springmvc mybatis的整合jar包,以及mysql,Junit,fastJson等的jar包,导入这些jar包 搭一个SSM的环境,可以使用SSM框架做一个简单的能够实现增删改查的小项目,具体的jar包及其版本如下 : aopalliance-1.0....

    spring3.0_mvc框架_06_上传的实现.flv

    基于spring 3.0mvc 框架的文件上传实现 1. spring使用了apache-commons下得上传组件,因此,我们需要引入两个jar包: ...2. 在springmvc-servlet.xml配置文件中,增加CommonsMultipartResoler配置:

    spring+struts+hibernate+dwr+jstl做的实例

    struts.jar spring-web.jar spring-webmvc.jar spring-portlet.jar struts.jar commons-fileupload.jar commons-httpclient.jar freemarker.jar jasperreports-1.3.3.jar commons-io.jar...

    springmvc+spring+mybatis整合所需jar

    springmvc+spring+mybatis整合所需jar aopalliance-1.0.jar ...jdbc-3.1.1.RELEASE.jar spring-test-3.2.0.RELEASE.jar spring-tx-3.1.1.RELEASE.jar spring-web-3.2.0.RELEASE.jar spring-webmvc-3.2.0.RELEASE.jar

    commons-fileupload&&commons-io.rar

    springmvc文件上传所需jar包,在Spring MVC中实现文件上传十分方便,它为文件上传提供了直接的支持

    FileUpload_.zip

    ajax提交包含input file和input text的表单。 项目是一个Maven项目,基于spring mvc

    springMVC 文件上传jar文件及源码

    springmvc fileupload 实现文件上传下载

    struts spring lib

    aspectjrt.jar aspectjweaver.jar ...spring-webmvc-struts.jar spring-webmvc.jar spring.jar standard.jar struts-spring-other-lib.rar struts.jar unittest.jar xercesImpl.jar xmlParserAPIs.jar

    springMVC用到的jar包

    aopalliance-1.0.jar commons-fileupload-1.2.2.jar commons-io-2.4.jar commons-...core-3.2.6.RELEASE.jar spring-expression-3.2.6.RELEASE.jar spring-web-3.2.6.RELEASE.jar spring-webmvc-3.2.6.RELEASE.jar

Global site tag (gtag.js) - Google Analytics