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

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

  1. <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>

springMVC的文件上传需要commons-fileupload 包的支持,需要引入。

  1. <dependency>
  2. <groupId>commons-fileupload</groupId>
  3. <artifactId>commons-fileupload</artifactId>
  4. <version>1.3.2</version>
  5. </dependency>

文件上传的jsp表单页面页面,文件名称为file:

  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>

文件上传的后台处理页面

  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方法中,用于判断这个请求是否是文件上传操作,具体的文件上传相关的操作都在这个方法中实现了。

  1. processedRequest = checkMultipart(request);
  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中

  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方法

  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来进行编程来实现文件的一系列操作了。

  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. }

SpringMVC源码分析--文件上传的更多相关文章

  1. THINKPHP源码学习--------文件上传类

    TP图片上传类的理解 在做自己项目上传图片的时候一直都有用到TP的上传图片类,所以要进入源码探索一下. 文件目录:./THinkPHP/Library/Think/Upload.class.php n ...

  2. 源码解读-文件上传angularFileUpload1

    angular-file-upload 1.文件上传模块的引入就不赘述,简单准备 2.初始化组件并绑定change事件 3.监听用户选择文件FileItem(change事件),push进文件数组qu ...

  3. PHP 大文件上传,支持断点续传,求具体方案、源码或者文件上传插件

    文件夹数据库处理逻辑 publicclass DbFolder { JSONObject root; public DbFolder() { this.root = new JSONObject(); ...

  4. springMVC源码分析--DispatcherServlet请求获取及处理

    在之前的博客springMVC源码分析--容器初始化(二)DispatcherServlet中我们介绍过DispatcherServlet,是在容器初始化过程中出现的,我们之前也说过Dispatche ...

  5. SpringMVC源码分析--容器初始化(五)DispatcherServlet

    上一篇博客SpringMVC源码分析--容器初始化(四)FrameworkServlet我们已经了解到了SpringMVC容器的初始化,SpringMVC对容器初始化后会进行一系列的其他属性的初始化操 ...

  6. SpringMVC源码分析(3)DispatcherServlet的请求处理流程

    <springmvc源码分析(2)dispatcherservlet的初始化>初始化DispatcherServlet的多个组件. 本文继续分析DispatcherServlet解析请求的 ...

  7. 框架-springmvc源码分析(一)

    框架-springmvc源码分析(一) 参考: http://www.cnblogs.com/heavenyes/p/3905844.html#a1 https://www.cnblogs.com/B ...

  8. [心得体会]SpringMVC源码分析

    1. SpringMVC (1) springmvc 是什么? 前端控制器, 主要控制前端请求分配请求任务到service层获取数据后反馈到springmvc的view层进行包装返回给tomcat, ...

  9. springMVC源码分析--国际化实现Session和Cookie(二)

    上一篇博客springMVC源码分析--国际化LocaleResolver(一)中我们介绍了springMVC提供的国际化的解决方案,接下来我们根据springMVC提供的解决方案来简单的实现一个多语 ...

随机推荐

  1. javaScript系列 [04]-javaScript的原型链

    [04]-javaScript的原型链 本文旨在花很少的篇幅讲清楚JavaScript语言中的原型链结构,很多朋友认为JavaScript中的原型链复杂难懂,其实不然,它们就像树上的一串猴子. 1.1 ...

  2. ios开发-将false和true,当做字典的值,并将字典转成字符串,上传到服务器

    今天遇到一个需求,将false和true,当做字典的值,并将字典转成字符串,上传到服务器. 可能这个需求大家遇到过,大部分原因是安卓的同事已经按这样的需求开发完了.我们只能跟随安卓的脚步了. (一)处 ...

  3. js高阶函数应用—函数柯里化和反柯里化(二)

    第上一篇文章中我们介绍了函数柯里化,顺带提到了偏函数,接下来我们继续话题,进入今天的主题-函数的反柯里化. 在上一篇文章中柯里化函数你可能需要去敲许多代码,理解很多代码逻辑,不过这一节我们讨论的反科里 ...

  4. 利用 Scrapy 爬取知乎用户信息

    思路:通过获取知乎某个大V的关注列表和被关注列表,查看该大V和其关注用户和被关注用户的详细信息,然后通过层层递归调用,实现获取关注用户和被关注用户的关注列表和被关注列表,最终实现获取大量用户信息. 一 ...

  5. [AHOI 2005]COMMON 约数研究

    Description Input 只有一行一个整数 N(0 < N < 1000000). Output 只有一行输出,为整数M,即f(1)到f(N)的累加和. Sample Input ...

  6. [HNOI 2004]敲砖块

    Description 在一个凹槽中放置了 n 层砖块.最上面的一层有n 块砖,从上到下每层依次减少一块砖.每块砖都有一个分值,敲掉这块砖就能得到相应的分值,如下图所示. 14 15 4 3 23 3 ...

  7. [HNOI 2009]有趣的数列

    Description 我们称一个长度为2n的数列是有趣的,当且仅当该数列满足以下三个条件: (1)它是从1到2n共2n个整数的一个排列{ai}: (2)所有的奇数项满足a1<a3<…&l ...

  8. [SDOI2008]Sue的小球

    题目描述 Sue和Sandy最近迷上了一个电脑游戏,这个游戏的故事发在美丽神秘并且充满刺激的大海上,Sue有一支轻便小巧的小船.然而,Sue的目标并不是当一个海盗,而是要收集空中漂浮的彩蛋,Sue有一 ...

  9. UVALive - 3938:"Ray, Pass me the dishes!"

    优美的线段树 #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring& ...

  10. ●BZOJ 2588 Spoj 10628. Count on a tree

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=2588 题解: 主席树,在线,(求LCA)感觉主席树真的好厉害...在原树上建主席树.即对于原 ...