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系列的瀏覽器都可以拋出異常並繼續執行異常處理的方法體。