multipart/form-data编码方式支持基于表单的文件上传。
使用MultipartResolver进行文件上传的简单分析:
MultipartResolver的接口定义如下:
public interface MultipartResolver{
boolean isMultipart(HttpServletRequest request);
MultipartHttpsServletRequest resolverMultipart(HttpServletRequest request)throws MultipartException;
void cleanupMultipart(MultipartHttpServletRequest request);
}
MultipartResolver 位于 HandlerMapping 之前,请求一来就交由它来处理。当 Web 请求到达 DispatcherServlet 并等待处理的时候,
DispatcherServlet 首先会检查能否从自的 WebApplicationContext 中找到一个名称为 multipartResolver(由 DispatcherServlet 的
常量 MULTIPART_RESOLVER_BEAN_NAME 所决定)的 MultipartResolver 实例。如果能够获得一个 MultipartResolver 的实例,DispatcherServlet
将调用 MultipartResolver 的 isMultipart(request) 方法检查当前 Web 请求是否为 multipart类型。如果是,DispatcherServlet 将调用 MultipartResolver 的
resolveMultipart(request) 方法,对原始 request 进行装饰,并返回一个 MultipartHttpServletRequest 供后继处理流程使用(最初的 HttpServletRequest 被偷梁
换柱成了 MultipartHttpServletRequest),否则,直接返回最初的 HttpServletRequest
SpringMVC框架内为MultipartResolver提供了两个可用的实现类,即org.springframework.web.multipartcommons.CommonsMultipartResolver
和org.springframework.web.multipart.cos.CosMultipartResolver。前者使用CommonsFileUpload类库实现,后者则使用Oreilly Cos类库实现
我们选择使用CommonsFileUpload进行文件上传,需要在DispatcherServlet的WebApplicationContext中添加bean定义如下:
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver"
p:maxUploadSize="1000000">
<bean/>
CommonsMultipartResolver将负责分析当前multipart请求,然后将分析的结果附着到要返回的MultipartHttpservletRequest实例上。当后继处理
流程的controller处理web请求的时候,就可以使用特定的MultipartHttpsServletRequest进行上传文件的获取和处理。
但MultipartResolver返回MultipartHttpServlet给后继处理流程,并且后继处理流程中的组件也使用MultipartHttpServletRequest处理完相应的Web
请求,DispatcherServlet将保证调用MultipartResolver的CleanupMultipart()方法,释放处理文件上传过程中所占用的系统资源,这样,整个文件上传
的生命周期即告结束。
下面来介绍一下我实现的文件上传的例子
要实现文件上传,首先添加一个MultipartResolver的实例到DispatcherServlet的WebApplicationContext中。
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver"
p:maxUploadSize="1000000">
</bean>
为了使用SimpleFormController专门处理表单的提交,我们需要为数据绑定提供一个Command对象,定义如下:
public class FileUploadingCommand {
private byte[] fileToUpload;
private String comment;
public byte[] getFileToUpload() {
return fileToUpload;
}
public void setFileToUpload(byte[] fileToUpload) {
this.fileToUpload = fileToUpload;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
@Override
public String toString() {
return new ToStringBuilder(this).append("fileToUpload",fileToUpload).append("comment",comment).toString();
}
}
定义的最终的Controller实现类如下:
public class FileUploadFormController extends SimpleFormController{
@Override
protected void doSubmitAction(Object command) throws Exception {
FileUploadingCommand commandBean=(FileUploadingCommand)command;
byte[] fileContent=commandBean.getFileToUpload();
String comment=commandBean.getComment();
FileUtils.writeByteArrayToFile(new File("zhsi"), fileContent);
}
@Override
protected void initBinder(HttpServletRequest request,
ServletRequestDataBinder binder) throws Exception {
super.initBinder(request, binder);
binder.registerCustomEditor(byte[].class, new ByteArrayMultipartFileEditor());
}
}
为了在数据绑定过程数据能够成功转型,我们需要为DataBinder添加相应的自定义PropertyEditor实现,覆写SimpleFormController的initBinder()
方法可以达到目的。
下面是SpringMVC.xml配置文件:
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="login.do">login</prop>
</props>
</property>
</bean>
<bean name="login" class="com.web.springMVC.controller.FileUploadFormController">
<property name="commandName">
<value>command</value>
</property>
<!-- 这里直接实现了将请求参数绑定到对象上 -->
<property name="commandClass">
<value>com.web.springMVC.model.FileUploadingCommand</value>
</property>
<property name="successView" value="success"></property>
<bean/>
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver"
p:maxUploadSize="1000000">
</bean>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" /> <!-- 默认放在WebRoot下 -->
<property name="suffix" value=".jsp" />
</bean>
页面login.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="login.do" method="post" enctype="multipart/form-data">
选择上传文件<input name="fileToUpload" type="file"/><br/>
文件说明<textarea name="comment"></textarea>
<input name="submit" type="submit" value="提交"/>
</form>
</body>
</html>
页面success.jsp
<body>
<table>
<tbody>
<tr>
<td>User Info:</td>
</tr>
<tr>
<td><c:out value="${command.comment}"></c:out></td>
</tr>
</tbody>
</table>
</body>
上述便可以实现简单的文件上传了