您的位置:首页 > 编程语言 > Java开发

SpringMVC源码分析--文件上传

2016-12-17 16:34 399 查看
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: