springMVC为咱们提供了上传文件的内部支持,咱们只须要一些配置,而后就能够借助于sprinngMVC提供给咱们的接口完成文件上传的工做。javascript
首选找到与springMVC的前端控制器DispatchServlet相关的上下文,即\WEB-INF\configs\spring\mvc-dispatcher-servlet.xmlcss
在DispatchServlet的上下文中配置一个类型为org.springframework.web.multipart.commons.CommonsMultipartResolver的bean。html
<!--200*1024*1024即200M resolveLazily属性启用是为了推迟文件解析,以便捕获文件大小异常 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="maxUploadSize" value="209715200"/> <property name="defaultEncoding" value="UTF-8"/> <property name="resolveLazily" value="true"/> </bean>
这个bean专门用来为咱们解析上载的文件。这个bean能够配置三个属性:前端
maxUploadSize设置文件上传的大小上限,单位是Byte,因此200MB这种记得本身算好算数哦。java
defaultEncoding是默认编码,这里咱们用的是UTF-8。web
resolveLazily是延迟加载,这个设置为true,主要是为了提升性能,在须要的时候再进行解析。spring
咱们从这个类的类型名称中带有的Common前缀能够看出,它依赖了apache的jar包,是的,事实就是如此。所以,咱们须要在POM.xml中加入jar。apache
<dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.1</version> </dependency>
顺便提一下,这个jar包所依赖的commons-io的jar包也会自动加载,无须在pom中显示引入commons-io坐标。编程
而后咱们如今设计一个上传案例:浏览器
咱们设计请求localhost:8080/mvc/courses/upload
所以控制器类中添加一个方法:
@RequestMapping(value="/upload", method=RequestMethod.GET) public String showUploadPage(){ return "course_admin/file"; }
而后,咱们添加对应的JSP文件\WEB-INF\jsps\course_admin\file.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>HappyBKs Upload Page</title> <link rel="stylesheet" href="<%=request.getContextPath()%>/resources/css/main.css" type="text/css" /> </head> <body> <div align="center"> <h1>上传附件</h1> <form method="post" action="/courses/doUpload" enctype="multipart/form-data"> <input type="file" name="file"/> <input type="submit"/> </form> </div> </body> </html>
该页面的表单中包含了一个file类型的input和一个submit按钮,另一个值得注意的是,form自己与通常的表单相比在这里需要额外添加一个属性enctype="multipart/form-data",这是咱们在文件上传时所必须显示指明的属性,没有这个属性将没法完成文件上传工做。
这个表单提交后请求的url是localhost:8080/mvc/courses/doUpload,方法固然是POST。
所以,咱们需要继续为这个请求再建立一个控制器方法来响应这个URL请求。在以前就说了,springMVC在进行相应的配置以后,就能够经过springMVC提供的一些接口来完成上载文件功能的编程实践:
@RequestMapping(value="/doUpload", method=RequestMethod.POST) public String doUploadFile(@RequestParam("file") MultipartFile file) throws IOException { if(!file.isEmpty()){ log.info("Process file(getOriginalFilename): {}", file.getOriginalFilename()); log.info("Process file(getName): {}", file.getName()); log.info("Process file(getContentType): {}", file.getContentType()); log.info("Process file(getSize): {}", file.getSize()); FileUtils.copyInputStreamToFile(file.getInputStream(), new File("c:\\temp\\happyBKs\\", System.currentTimeMillis()+ file.getOriginalFilename())); } return "success"; }
这个接口是一个类——org.springframework.web.multipart.MultipartFile。
springMVC的源代码中的接口定义接口以下:
package org.springframework.web.multipart; import java.io.File; import java.io.IOException; import java.io.InputStream; import org.springframework.core.io.InputStreamSource; /** * A representation of an uploaded file received in a multipart request. * * <p>The file contents are either stored in memory or temporarily on disk. * In either case, the user is responsible for copying file contents to a * session-level or persistent store as and if desired. The temporary storages * will be cleared at the end of request processing. * * @author Juergen Hoeller * @author Trevor D. Cook * @since 29.09.2003 * @see org.springframework.web.multipart.MultipartHttpServletRequest * @see org.springframework.web.multipart.MultipartResolver */ public interface MultipartFile extends InputStreamSource { /** * Return the name of the parameter in the multipart form. * @return the name of the parameter (never {@code null} or empty) */ String getName(); /** * Return the original filename in the client's filesystem. * <p>This may contain path information depending on the browser used, * but it typically will not with any other than Opera. * @return the original filename, or the empty String if no file * has been chosen in the multipart form, or {@code null} * if not defined or not available */ String getOriginalFilename(); /** * Return the content type of the file. * @return the content type, or {@code null} if not defined * (or no file has been chosen in the multipart form) */ String getContentType(); /** * Return whether the uploaded file is empty, that is, either no file has * been chosen in the multipart form or the chosen file has no content. */ boolean isEmpty(); /** * Return the size of the file in bytes. * @return the size of the file, or 0 if empty */ long getSize(); /** * Return the contents of the file as an array of bytes. * @return the contents of the file as bytes, or an empty byte array if empty * @throws IOException in case of access errors (if the temporary store fails) */ byte[] getBytes() throws IOException; /** * Return an InputStream to read the contents of the file from. * The user is responsible for closing the stream. * @return the contents of the file as stream, or an empty stream if empty * @throws IOException in case of access errors (if the temporary store fails) */ @Override InputStream getInputStream() throws IOException; /** * Transfer the received file to the given destination file. * <p>This may either move the file in the filesystem, copy the file in the * filesystem, or save memory-held contents to the destination file. * If the destination file already exists, it will be deleted first. * <p>If the file has been moved in the filesystem, this operation cannot * be invoked again. Therefore, call this method just once to be able to * work with any storage mechanism. * <p><strong>Note:</strong> when using Servlet 3.0 multipart support you * need to configure the location relative to which files will be copied * as explained in {@link javax.servlet.http.Part#write}. * @param dest the destination file * @throws IOException in case of reading or writing errors * @throws IllegalStateException if the file has already been moved * in the filesystem and is not available anymore for another transfer */ void transferTo(File dest) throws IOException, IllegalStateException; }
这个接口实现的类对象能够得到文件的本地文件名、内容类型、大小等信息。
那么控制器的方法参数MultipartFile如何与请求提交的表单元素相关联呢?POST请求的表单元素是一种请求参数,创建请求参数与控制器方法参数之间的映射关联,固然用的是注解@RequestParam,如上面的控制器方法代码所示。这里@RequestParam("file")的值“file”与请求提交的表单中form的<input type="file" name="file"/>中的name="file"名称对应,这样表单中name是file的元素的值就绑定到了控制器方法参数上,它的类型会被转换成MultipartFile,整个复杂的转换过程都由springMVC咱们完成,咱们本身要作的仅仅是使用这个留给咱们的接口MultipartFile。
这里,咱们还将MultipartFile的各个属性也一并输出到日志。
值得注意的是,实际的文件处理用了FileUtils来处理文件的相关操做,这是commons-io中十分有用的工具类,来完成文件的拷贝、文件流的操做等。
public static void copyInputStreamToFile(InputStream source, File destination) throws IOException
FileUtils.copyInputStreamToFile方法用于拷贝文件,第一个参数是拷贝文件源的流,正好MultipartFile有一个获取输入流的方法file.getInputStream()。输出的文件流,新建一个本地服务器的文件流,本地文件名是一个时间戳加上MultipartFile的本来的文件名。
咱们继续为上传成功后转发的页面进行添加\WEB-INF\jsps\success.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> <link rel="stylesheet" href="<%=request.getContextPath()%>/resources/css/main.css" type="text/css"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <div align="center"> <h1>Success!</h1> </div> </body> </html>
接下来,看看实际的运行效果:
请求http://localhost:8080/mvc/courses/upload
选择一个图片文件好了
提交以后,POST请求带着表单数据请求:
控制台输出日志:
经过这个日志输出能够看到:
getOriginalFilename是获得文件本身的名字
getName是获得请求提交的表单中的元素名字
getContentType获得的是文件的类型
getSize获得文件的大小
以后控制器将请求处理以后,转向\WEB-INF\jsps\success.jsp
本地服务器存储的位置也出现了相应的图片文件,命名方法就是咱们本身定义的方式,带时间戳哦。
好,假如我如今上传个超大文件,好比dota2的压缩安装文件:
提交以后,服务就崩溃了:
控制台输出如下错误:
654431 [http-apr-8080-exec-5] WARN org.springframework.web.multipart.commons.CommonsMultipartResolver - Failed to perform multipart cleanup for servlet request org.springframework.web.multipart.MaxUploadSizeExceededException: Maximum upload size of 209715200 bytes exceeded; nested exception is org.apache.commons.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (9686027054) exceeds the configured maximum (209715200) at org.springframework.web.multipart.commons.CommonsMultipartResolver.parseRequest(CommonsMultipartResolver.java:162) at org.springframework.web.multipart.commons.CommonsMultipartResolver$1.initializeMultipart(CommonsMultipartResolver.java:134) at org.springframework.web.multipart.support.AbstractMultipartHttpServletRequest.getMultipartFiles(AbstractMultipartHttpServletRequest.java:126) at org.springframework.web.multipart.support.AbstractMultipartHttpServletRequest.getMultiFileMap(AbstractMultipartHttpServletRequest.java:106) at org.springframework.web.multipart.commons.CommonsMultipartResolver.cleanupMultipart(CommonsMultipartResolver.java:191) at org.springframework.web.servlet.DispatcherServlet.cleanupMultipart(DispatcherServlet.java:1107) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:895) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967) at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:869) at javax.servlet.http.HttpServlet.service(HttpServlet.java:650) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843) at javax.servlet.http.HttpServlet.service(HttpServlet.java:731) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:957) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:620) at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2476) at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2465) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:745) Caused by: org.apache.commons.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (9686027054) exceeds the configured maximum (209715200) at org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl.<init>(FileUploadBase.java:965) at org.apache.commons.fileupload.FileUploadBase.getItemIterator(FileUploadBase.java:310) at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:334) at org.apache.commons.fileupload.servlet.ServletFileUpload.parseRequest(ServletFileUpload.java:115) at org.springframework.web.multipart.commons.CommonsMultipartResolver.parseRequest(CommonsMultipartResolver.java:158) ... 33 more 654431 [http-apr-8080-exec-5] WARN org.springframework.web.multipart.commons.CommonsMultipartResolver - Failed to perform multipart cleanup for servlet request org.springframework.web.multipart.MaxUploadSizeExceededException: Maximum upload size of 209715200 bytes exceeded; nested exception is org.apache.commons.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (9686027054) exceeds the configured maximum (209715200) at org.springframework.web.multipart.commons.CommonsMultipartResolver.parseRequest(CommonsMultipartResolver.java:162) at org.springframework.web.multipart.commons.CommonsMultipartResolver$1.initializeMultipart(CommonsMultipartResolver.java:134) at org.springframework.web.multipart.support.AbstractMultipartHttpServletRequest.getMultipartFiles(AbstractMultipartHttpServletRequest.java:126) at org.springframework.web.multipart.support.AbstractMultipartHttpServletRequest.getMultiFileMap(AbstractMultipartHttpServletRequest.java:106) at org.springframework.web.multipart.commons.CommonsMultipartResolver.cleanupMultipart(CommonsMultipartResolver.java:191) at org.springframework.web.servlet.DispatcherServlet.cleanupMultipart(DispatcherServlet.java:1107) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:895) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967) at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:869) at javax.servlet.http.HttpServlet.service(HttpServlet.java:650) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843) at javax.servlet.http.HttpServlet.service(HttpServlet.java:731) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:957) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:620) at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2476) at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2465) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:745) Caused by: org.apache.commons.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (9686027054) exceeds the configured maximum (209715200) at org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl.<init>(FileUploadBase.java:965) at org.apache.commons.fileupload.FileUploadBase.getItemIterator(FileUploadBase.java:310) at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:334) at org.apache.commons.fileupload.servlet.ServletFileUpload.parseRequest(ServletFileUpload.java:115) at org.springframework.web.multipart.commons.CommonsMultipartResolver.parseRequest(CommonsMultipartResolver.java:158) ... 33 more 654439 [http-apr-8080-exec-5] DEBUG org.springframework.web.servlet.DispatcherServlet - Could not complete request org.springframework.web.multipart.MaxUploadSizeExceededException: Maximum upload size of 209715200 bytes exceeded; nested exception is org.apache.commons.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (9686027054) exceeds the configured maximum (209715200) at org.springframework.web.multipart.commons.CommonsMultipartResolver.parseRequest(CommonsMultipartResolver.java:162) at org.springframework.web.multipart.commons.CommonsMultipartResolver$1.initializeMultipart(CommonsMultipartResolver.java:134) at org.springframework.web.multipart.support.AbstractMultipartHttpServletRequest.getMultipartFiles(AbstractMultipartHttpServletRequest.java:126) at org.springframework.web.multipart.support.AbstractMultipartHttpServletRequest.getFile(AbstractMultipartHttpServletRequest.java:85) at org.springframework.web.method.annotation.RequestParamMethodArgumentResolver.resolveName(RequestParamMethodArgumentResolver.java:169) at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:90) at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:99) at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:161) at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:128) at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:832) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:743) at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:961) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:895) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967) at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:869) at javax.servlet.http.HttpServlet.service(HttpServlet.java:650) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843) at javax.servlet.http.HttpServlet.service(HttpServlet.java:731) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:957) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:620) at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2476) at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2465) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:745) Caused by: org.apache.commons.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (9686027054) exceeds the configured maximum (209715200) at org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl.<init>(FileUploadBase.java:965) at org.apache.commons.fileupload.FileUploadBase.getItemIterator(FileUploadBase.java:310) at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:334) at org.apache.commons.fileupload.servlet.ServletFileUpload.parseRequest(ServletFileUpload.java:115) at org.springframework.web.multipart.commons.CommonsMultipartResolver.parseRequest(CommonsMultipartResolver.java:158) ... 40 more 654439 [http-apr-8080-exec-5] DEBUG org.springframework.web.servlet.DispatcherServlet - Could not complete request org.springframework.web.multipart.MaxUploadSizeExceededException: Maximum upload size of 209715200 bytes exceeded; nested exception is org.apache.commons.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (9686027054) exceeds the configured maximum (209715200) at org.springframework.web.multipart.commons.CommonsMultipartResolver.parseRequest(CommonsMultipartResolver.java:162) at org.springframework.web.multipart.commons.CommonsMultipartResolver$1.initializeMultipart(CommonsMultipartResolver.java:134) at org.springframework.web.multipart.support.AbstractMultipartHttpServletRequest.getMultipartFiles(AbstractMultipartHttpServletRequest.java:126) at org.springframework.web.multipart.support.AbstractMultipartHttpServletRequest.getFile(AbstractMultipartHttpServletRequest.java:85) at org.springframework.web.method.annotation.RequestParamMethodArgumentResolver.resolveName(RequestParamMethodArgumentResolver.java:169) at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:90) at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:99) at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:161) at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:128) at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:832) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:743) at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:961) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:895) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967) at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:869) at javax.servlet.http.HttpServlet.service(HttpServlet.java:650) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843) at javax.servlet.http.HttpServlet.service(HttpServlet.java:731) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:957) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:620) at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2476) at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2465) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:745) Caused by: org.apache.commons.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (9686027054) exceeds the configured maximum (209715200) at org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl.<init>(FileUploadBase.java:965) at org.apache.commons.fileupload.FileUploadBase.getItemIterator(FileUploadBase.java:310) at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:334) at org.apache.commons.fileupload.servlet.ServletFileUpload.parseRequest(ServletFileUpload.java:115) at org.springframework.web.multipart.commons.CommonsMultipartResolver.parseRequest(CommonsMultipartResolver.java:158) ... 40 more
这个异常应该如何捕获呢,虽然这种异常不会怎样,也确实证实了springMVC的这个上载文件的组件能够完成对文件大小的限制,可是如何才能捕获这个异常呢?
不要妄想直接在控制器类中捕获,由于,若是直接按照刚才的配置和代码,文件过大抛出异常时,根本就没有到/mvc/courses/doUpload对应的控制器方法doUploadFile就已经结束了。不信,咱们作个实验:
我在方法的开始增长一句日志输出:
@RequestMapping(value="/doUpload", method=RequestMethod.POST) public String doUploadFile(@RequestParam("file") MultipartFile file) throws IOException { log.info("step into doUploadFile............................"); if(!file.isEmpty()){ log.info("Process file(getOriginalFilename): {}", file.getOriginalFilename()); log.info("Process file(getName): {}", file.getName()); log.info("Process file(getContentType): {}", file.getContentType()); log.info("Process file(getSize): {}", file.getSize()); FileUtils.copyInputStreamToFile(file.getInputStream(), new File("c:\\temp\\happyBKs\\", System.currentTimeMillis()+ file.getOriginalFilename())); } return "success"; }
可是当我像刚才同样上载超大文件,提交表单以后,并无输出过
"step into doUploadFile............................",也就是说,抛出上载文件过大异常时,程序根本没有进入控制器方法的执行体。那么该怎么办呢?
咱们需要单独为控制器写一个处理异常的方法,用到注解@ExceptionHandler。
@ExceptionHandler(Exception.class) public void handleException(Exception ex,HttpServletRequest request,HttpServletResponse response){ log.info("step into handleException............................"); StringBuffer sb = new StringBuffer(); sb.append("<script language='javascript'>history.go(-1);alert('"); if (ex instanceof org.springframework.web.multipart.MaxUploadSizeExceededException){ sb.append("文件大小不该大于"+((MaxUploadSizeExceededException)ex).getMaxUploadSize()/1000+"kb"); } else{ sb.append("上传异常!"); } sb.append("!');</script>"); try { System.out.println(sb.toString()); response.setContentType("text/html; charset=utf-8"); response.getWriter().println(sb.toString()); response.getWriter().flush(); } catch (IOException e) { e.printStackTrace(); } return; }
当按照刚才的方法上载大文件时,这时候,依然会抛出异常,可是,方法已经能够捕获了并采起措施了:日志输出以下:
好吧,我前端不在行,也懒得弄了,原本是想把这个用浏览器对话框输出的,不过验证了异常可以侦测到并实现相应的操做就已经达到目的了。可是,这里有个使人不解的地方是,我使用IE/EDGE浏览器会出现异常没法抛出的卡死现象,webkit系列的浏览器都可以抛出异常并继续执行异常处理的方法体。