方法一:
在Spring配置文件里不配置下面这个拦截器
<!-- 上传文件拦截,设置最大上传文件大小 1G -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="1073741824"/>
</bean>
则在Controller方法里可以通过下面的方法获取上传的文件。这跟用Servlet时是一样的。
@RequestMapping(value="uploadFile", method=RequestMethod.POST)
public @ResponseBody String uploadFile(HttpServletRequest request) {
System.out.println("***** uploadFile *****");
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
try {
List<FileItem> items = upload.parseRequest(request);
for (FileItem item : items) {
if (null != item.getName() && item.getName().trim() != "") {
System.out.println("item name: " + item.getName());
// file = new File(uploadPath + item.getName());
// item.write(file);
}
}
} catch (FileUploadException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return "complete";
}
方法二:
如果在Spring配置文件里配置了上面的拦截器,在Controller的方法里就不能用上面的方法获取文件,而是通过下面的方法。(注意参数是MultipartHttpServletRequest类型,而不是HttpServletRequest类型)
@RequestMapping(value="uploadFile", method=RequestMethod.POST)
public @ResponseBody String uploadFile(MultipartHttpServletRequest request) {
System.out.println("***** uploadFile *****");
MultiValueMap<String, MultipartFile> map = request.getMultiFileMap();
Set<String> set = map.keySet();
Iterator<String> iter = set.iterator();
while (iter.hasNext()) {
List<MultipartFile> list = map.get(iter.next());
for (MultipartFile multiFile : list) {
System.out.println(multiFile.getOriginalFilename());
}
}
return "complete";
}
或下面的方法。
@RequestMapping(value="uploadFile", method=RequestMethod.POST)
public @ResponseBody String uploadFile(
@RequestParam(value="file1") MultipartFile file1,
@RequestParam(value="file2") MultipartFile file2,
@RequestParam(value="file3") MultipartFile file3,
HttpServletRequest request) {
System.out.println("***** uploadFile *****");
System.out.println("file1: " + file1.getOriginalFilename());
System.out.println("file2: " + file2.getOriginalFilename());
System.out.println("file3: " + file3.getOriginalFilename());
return "complete";
}
(注意:@RequestParm(value=<elm_name>)里的<elm_name>是对应html里的name属性,而不是id属性。如:<input type="file" name="file1">)
原因是,在DispatcherServlet里,doDispatch方法会首先检查Spring有没有加载任何MultipartResolver。(就是配置文件里的CommonMultipartResolver了)。
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
processedRequest = <span style="color:#FF0000;"><strong>checkMultipart</strong></span>(request);
multipartRequestParsed = (processedRequest != request);
...
如果有,并且这个request是一个multipart request,就会调用resolveMultipart方法,把request里的multipart files parse出来(调用ServletFileUpload.parseRequest(request)),放在一个MultipartHttpServletRequest对象里,并返回这个对象。
protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException {
<strong><span style="color:#FF0000;">if (this.multipartResolver != null && this.multipartResolver.isMultipart(request))</span></strong> {
if (request instanceof MultipartHttpServletRequest) {
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 <strong><span style="color:#FF0000;">this.multipartResolver.resolveMultipart(request);</span></strong>
}
}
// If not returned before: return original request.
return request;
}
由于HttpServletRequest在这里经过一次parseRequest(request)操作,所以在Controller方法里不能再通过这种方法拿出multipart file了。而只能传入一个MultipartHttpServletRequest对象,从这个对象里拿出multipart file。
获取上传进度:
因为CommonMultipartResolver没有帮我们添加监听器,如果要获取上传进度,就需要自己扩展这个类。重写parseRequest()方法,在里面添加监听器。
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUpload;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import com.listener.FileUploadProgressListener;
public class CustomMultipartResolver extends CommonsMultipartResolver {
/**
* 重写parseRequest方法,在parseRequest()之前添加监听器
*/
@Override
protected MultipartParsingResult parseRequest(HttpServletRequest request) throws MultipartException {
String encoding = determineEncoding(request);
FileUpload fileUpload = prepareFileUpload(encoding);
// 在这里添加监听器,其他照抄CommonsMultipartResolver.parseRequest(HttpServletRequest request)
fileUpload.setProgressListener(new FileUploadProgressListener(request.getSession()));
try {
List<FileItem> fileItems = ((ServletFileUpload) fileUpload).parseRequest(request);
return parseFileItems(fileItems, encoding);
}
catch (FileUploadBase.SizeLimitExceededException ex) {
throw new MaxUploadSizeExceededException(fileUpload.getSizeMax(), ex);
}
catch (FileUploadException ex) {
throw new MultipartException("Could not parse multipart servlet request", ex);
}
}
}
然后在Spring里配置这个扩展的类,代替CommonMultipartResulver。
<!-- 上传文件拦截,设置最大上传文件大小 1G -->
<bean id="multipartResolver" class="com.interceptor.CustomMultipartResolver">
<property name="maxUploadSize" value="1073741824"/>
</bean>