SpringMVC源码分析--文件上传
SpringMVC提供了文件上传的功能,接下来我们就简单了解一下SpringMVC文件上传的开发及大致过程。
首先需要在springMVC的配置文件中配置文件上传解析器
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
springMVC的文件上传需要commons-fileupload 包的支持,需要引入。
<dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.2</version> </dependency>
文件上传的jsp表单页面页面,文件名称为file:
<form id='fForm' class="form-actions form-horizontal" action="/file/upload.action" encType="multipart/form-data" target="uploadf" method="post"> <div class="control-group"> <label class="control-label">上传文件:</label> <div class="controls"> <input type="file" name="file" style="width:550"> </div> </div> <div class="control-group"> <div class="controls"> <button type="button" id="subbut" class="btn">submit</button> </div> </div> </form>
文件上传的后台处理页面
@Controller
@RequestMapping("/file")
public class FileUpload {
@RequestMapping("/upload")
@ResponseBody
public String upload(@RequestParam(value = "file", required = false)MultipartFile... files ){
for (MultipartFile f : files) {
if (f.getSize() > 0) {
File targetFile = new File("1.jpg");
try {
f.transferTo(targetFile);
} catch (IllegalStateException | IOException e) {
e.printStackTrace();
}
}
}
return null;
}
@RequestMapping("/uploads")
public String uploads(){
return "fileupload";
}
}
这样就可以在jsp页面中提交一个图片,后台将图片保存到工程目录下,页面如下:
接下来我们了解一下文件上传到达处理的Controller时做的预处理
在请求到达DispatcherServelet时,对文件上传处理的操作是在doDispatch方法中,用于判断这个请求是否是文件上传操作,具体的文件上传相关的操作都在这个方法中实现了。
processedRequest = checkMultipart(request);
protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException {
//首先判断请求是否是文件上传
if (this.multipartResolver != null && this.multipartResolver.isMultipart(request)) {
if (WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class) != null) {
logger.debug("Request is already a MultipartHttpServletRequest - if not in a forward, " +
"this typically results from an additional MultipartFilter in web.xml");
}
else if (request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) instanceof MultipartException) {
logger.debug("Multipart resolution failed for current request before - " +
"skipping re-resolution for undisturbed error rendering");
}
else {
return this.multipartResolver.resolveMultipart(request);
}
}
//如果不是文件上传则直接返回请求
// If not returned before: return original request.
return request;
}
this.multipartResolver.isMultipart(request)这个方法操作用来判断请求是否是文件上传操作,具体实现是在我们配置的multipartResolver中
@Override
public boolean isMultipart(HttpServletRequest request) {
return (request != null && ServletFileUpload.isMultipartContent(request));
}
ServletFileUpload.isMultipart方法判断请求是否是文件上传的实现是在commons-fileupload包中了,这就是我们为什么需要引入commons-fileupload的原因
当我们已经判断请求是文件上传的请求时,接下来的操作是在this.multipartResolver.resolveMultipart(request);中了。
CommonsMultipartResolver类中的resolveMultipart方法
@Override
public MultipartHttpServletRequest resolveMultipart(final HttpServletRequest request) throws MultipartException {
Assert.notNull(request, "Request must not be null");
//this.resolveLazily默认值是false
if (this.resolveLazily) {
return new DefaultMultipartHttpServletRequest(request) {
@Override
protected void initializeMultipart() {
MultipartParsingResult parsingResult = parseRequest(request);
setMultipartFiles(parsingResult.getMultipartFiles());
setMultipartParameters(parsingResult.getMultipartParameters());
setMultipartParameterContentTypes(parsingResult.getMultipartParameterContentTypes());
}
};
}
else {
MultipartParsingResult parsingResult = parseRequest(request);
return new DefaultMultipartHttpServletRequest(request, parsingResult.getMultipartFiles(),
parsingResult.getMultipartParameters(), parsingResult.getMultipartParameterContentTypes());
}
}
具体的解析过程我们就不分析了,最终结果是生成一个DefaultMultipartHttpServletRequest,其主要的实现就是将我们在前端页面上传的文件file,生成MultipartFile对象,这就是为什么在Controller中,我们file参数的类型是MultipartFile,如下,这样我们就可以通过MultipartFile来进行编程来实现文件的一系列操作了。
public String upload(@RequestParam(value = "file", required = false)MultipartFile... files ){
for (MultipartFile f : files) {
if (f.getSize() > 0) {
File targetFile = new File("1.jpg");
try {
f.transferTo(targetFile);
} catch (IllegalStateException | IOException e) {
e.printStackTrace();
}
}
}
return null;
}
SpringMVC源码分析--文件上传的更多相关文章
- THINKPHP源码学习--------文件上传类
TP图片上传类的理解 在做自己项目上传图片的时候一直都有用到TP的上传图片类,所以要进入源码探索一下. 文件目录:./THinkPHP/Library/Think/Upload.class.php n ...
- 源码解读-文件上传angularFileUpload1
angular-file-upload 1.文件上传模块的引入就不赘述,简单准备 2.初始化组件并绑定change事件 3.监听用户选择文件FileItem(change事件),push进文件数组qu ...
- PHP 大文件上传,支持断点续传,求具体方案、源码或者文件上传插件
文件夹数据库处理逻辑 publicclass DbFolder { JSONObject root; public DbFolder() { this.root = new JSONObject(); ...
- springMVC源码分析--DispatcherServlet请求获取及处理
在之前的博客springMVC源码分析--容器初始化(二)DispatcherServlet中我们介绍过DispatcherServlet,是在容器初始化过程中出现的,我们之前也说过Dispatche ...
- SpringMVC源码分析--容器初始化(五)DispatcherServlet
上一篇博客SpringMVC源码分析--容器初始化(四)FrameworkServlet我们已经了解到了SpringMVC容器的初始化,SpringMVC对容器初始化后会进行一系列的其他属性的初始化操 ...
- SpringMVC源码分析(3)DispatcherServlet的请求处理流程
<springmvc源码分析(2)dispatcherservlet的初始化>初始化DispatcherServlet的多个组件. 本文继续分析DispatcherServlet解析请求的 ...
- 框架-springmvc源码分析(一)
框架-springmvc源码分析(一) 参考: http://www.cnblogs.com/heavenyes/p/3905844.html#a1 https://www.cnblogs.com/B ...
- [心得体会]SpringMVC源码分析
1. SpringMVC (1) springmvc 是什么? 前端控制器, 主要控制前端请求分配请求任务到service层获取数据后反馈到springmvc的view层进行包装返回给tomcat, ...
- springMVC源码分析--国际化实现Session和Cookie(二)
上一篇博客springMVC源码分析--国际化LocaleResolver(一)中我们介绍了springMVC提供的国际化的解决方案,接下来我们根据springMVC提供的解决方案来简单的实现一个多语 ...
随机推荐
- HDFS- High Availability
NameNode High Availability Background Hadoop2.0.0之前,NameNode存在单点失败(single point of failure (SPOF) )问 ...
- 设计APP时我们该怎么做
不得不承认,手机APP已经渗透到我们的生活中,根据数据统计,人们每天平均有3.9个小时是花费在手机APP的使用上的,可以预见,手机APP正在改变我们的生活.手机APP受到人们的欢迎,很多商家也看到了其 ...
- [LeetCode] The Maze 迷宫
There is a ball in a maze with empty spaces and walls. The ball can go through empty spaces by rolli ...
- 机器学习技法:03 Kernel Support Vector Machine
Roadmap Kernel Trick Polynomial Kernel Gaussian Kernel Comparison of Kernels Summary
- Event 发布与订阅(一)
前言 主要讲的是发布与订阅在Event中的一个简单实现用来加深理解. C #中的事件(Event)的理解: 事件具有以下属性:(From Events) 发行者确定何时引发事件:订户确定对事件作出何种 ...
- 计蒜客NOIP2017提高组模拟赛(三)day2-小区划分
传送门 dp,注意边界 #include<cstdio> #include<cstdlib> #include<algorithm> #include<cst ...
- 《java技术》第二次作业
(一)学习总结 1.什么是构造方法?什么是构造方法的重载? 1)没有返回值,名字与类名相同,当新对象被创建的时候,构造函数会被调用,要想构造函数,必须声明对象并对其初始化.每一个类都有构造函数,如果没 ...
- Java Web -【分页功能】详解
分页简介 分页功能在网页中是非常常见的一个功能,其作用也就是将数据分割成多个页面来进行显示. 使用场景: 当取到的数据量达到一定的时候,就需要使用分页来进行数据分割. 当我们不使用分页功能的时候,会面 ...
- django之模板显示静态文件
由于django的模板渲染机制,图片不能直接引用,否则不会显示. <img src="/static/img/logo.jpg"> 可以看出图片的大小轮廓,但并不显示内 ...
- AngularJs开发——指令与控制器间的通信
(原文:http://www.html5jscss.com/controller-between-directive.html) 指令与控制器之间通信,跟控制器间的通信.指令间通信也类似,也是下几种方 ...