SpringMVC源码分析--文件上传

来源:互联网 发布:日系男装淘宝 知乎 编辑:程序博客网 时间:2024/06/05 08:05


SpringMVC提供了文件上传的功能,接下来我们就简单了解一下SpringMVC文件上传的开发及大致过程。

首先需要在springMVC的配置文件中配置文件上传解析器

[html] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>    
springMVC的文件上传需要commons-fileupload 包的支持,需要引入。

[html] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. <dependency>  
  2.             <groupId>commons-fileupload</groupId>  
  3.             <artifactId>commons-fileupload</artifactId>  
  4.             <version>1.3.2</version>  
  5.         </dependency>  
文件上传的jsp表单页面页面,文件名称为file:

[html] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. <form id='fForm' class="form-actions form-horizontal" action="/file/upload.action"   
  2.               encType="multipart/form-data" target="uploadf" method="post">  
  3.                  <div class="control-group">  
  4.                     <label class="control-label">上传文件:</label>  
  5.                     <div class="controls">  
  6.                         <input type="file"  name="file" style="width:550">  
  7.                               
  8.                     </div>  
  9.                 </div>  
  10.                  <div class="control-group">  
  11.                     <div class="controls">  
  12.                     <button type="button" id="subbut" class="btn">submit</button>  
  13.                     </div>  
  14.                 </div>  
  15.         </form>  
文件上传的后台处理页面

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. @Controller  
  2. @RequestMapping("/file")  
  3. public class FileUpload {  
  4.   
  5.     @RequestMapping("/upload")  
  6.     @ResponseBody  
  7.     public String upload(@RequestParam(value = "file", required = false)MultipartFile... files ){  
  8.           
  9.         for (MultipartFile f : files) {  
  10.             if (f.getSize() > 0) {  
  11.                 File targetFile = new File("1.jpg");  
  12.                 try {  
  13.                     f.transferTo(targetFile);  
  14.                 } catch (IllegalStateException | IOException e) {  
  15.                     e.printStackTrace();  
  16.                 }  
  17.             }  
  18.         }  
  19.           
  20.         return null;  
  21.     }  
  22.       
  23.     @RequestMapping("/uploads")  
  24.     public String uploads(){  
  25.         return "fileupload";  
  26.     }  
  27. }  
这样就可以在jsp页面中提交一个图片,后台将图片保存到工程目录下,页面如下:

接下来我们了解一下文件上传到达处理的Controller时做的预处理

在请求到达DispatcherServelet时,对文件上传处理的操作是在doDispatch方法中,用于判断这个请求是否是文件上传操作,具体的文件上传相关的操作都在这个方法中实现了。

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. processedRequest = checkMultipart(request);  
[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException {  
  2.         //首先判断请求是否是文件上传  
  3.         if (this.multipartResolver != null && this.multipartResolver.isMultipart(request)) {  
  4.             if (WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class) != null) {  
  5.                 logger.debug("Request is already a MultipartHttpServletRequest - if not in a forward, " +  
  6.                         "this typically results from an additional MultipartFilter in web.xml");  
  7.             }  
  8.             else if (request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) instanceof MultipartException) {  
  9.                 logger.debug("Multipart resolution failed for current request before - " +  
  10.                         "skipping re-resolution for undisturbed error rendering");  
  11.             }  
  12.             else {  
  13.                 return this.multipartResolver.resolveMultipart(request);  
  14.             }  
  15.         }  
  16.         //如果不是文件上传则直接返回请求  
  17.         // If not returned before: return original request.  
  18.         return request;  
  19.     }  

this.multipartResolver.isMultipart(request)这个方法操作用来判断请求是否是文件上传操作,具体实现是在我们配置的multipartResolver中

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. @Override  
  2.     public boolean isMultipart(HttpServletRequest request) {  
  3.         return (request != null && ServletFileUpload.isMultipartContent(request));  
  4.     }  
ServletFileUpload.isMultipart方法判断请求是否是文件上传的实现是在commons-fileupload包中了,这就是我们为什么需要引入commons-fileupload的原因

当我们已经判断请求是文件上传的请求时,接下来的操作是在this.multipartResolver.resolveMultipart(request);中了。

CommonsMultipartResolver类中的resolveMultipart方法

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. @Override  
  2.     public MultipartHttpServletRequest resolveMultipart(final HttpServletRequest request) throws MultipartException {  
  3.         Assert.notNull(request, "Request must not be null");  
  4.         //this.resolveLazily默认值是false  
  5.         if (this.resolveLazily) {  
  6.             return new DefaultMultipartHttpServletRequest(request) {  
  7.                 @Override  
  8.                 protected void initializeMultipart() {  
  9.                     MultipartParsingResult parsingResult = parseRequest(request);  
  10.                     setMultipartFiles(parsingResult.getMultipartFiles());  
  11.                     setMultipartParameters(parsingResult.getMultipartParameters());  
  12.                     setMultipartParameterContentTypes(parsingResult.getMultipartParameterContentTypes());  
  13.                 }  
  14.             };  
  15.         }  
  16.         else {  
  17.             MultipartParsingResult parsingResult = parseRequest(request);  
  18.             return new DefaultMultipartHttpServletRequest(request, parsingResult.getMultipartFiles(),  
  19.                     parsingResult.getMultipartParameters(), parsingResult.getMultipartParameterContentTypes());  
  20.         }  
  21.     }  

具体的解析过程我们就不分析了,最终结果是生成一个DefaultMultipartHttpServletRequest,其主要的实现就是将我们在前端页面上传的文件file,生成MultipartFile对象,这就是为什么在Controller中,我们file参数的类型是MultipartFile,如下,这样我们就可以通过MultipartFile来进行编程来实现文件的一系列操作了。

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. public String upload(@RequestParam(value = "file", required = false)MultipartFile... files ){  
  2.           
  3.         for (MultipartFile f : files) {  
  4.             if (f.getSize() > 0) {  
  5.                 File targetFile = new File("1.jpg");  
  6.                 try {  
  7.                     f.transferTo(targetFile);  
  8.                 } catch (IllegalStateException | IOException e) {  
  9.                     e.printStackTrace();  
  10.                 }  
  11.             }  
  12.         }  
  13.           
  14.         return null;  
  15.     } 

0 0
原创粉丝点击