文档章节

springMVC笔记系列(21)——springMVC自带的上传文件功能实现

HappyBKs
 HappyBKs
发布于 2016/07/05 18:16
字数 3433
阅读 1016
收藏 6

springMVC为我们提供了上传文件的内部支持,我们只需要一些配置,然后就可以借助于sprinngMVC提供给我们的接口完成文件上传的工作。

首选找到与springMVC的前端控制器DispatchServlet相关的上下文,即\WEB-INF\configs\spring\mvc-dispatcher-servlet.xml

在DispatchServlet的上下文中配置一个类型为org.springframework.web.multipart.commons.CommonsMultipartResolver的bean。

    <!--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这种记得自己算好算数哦。

defaultEncoding是默认编码,这里我们用的是UTF-8。

resolveLazily是延迟加载,这个设置为true,主要是为了提高性能,在需要的时候再进行解析。

我们从这个类的类型名称中带有的Common前缀可以看出,它依赖了apache的jar包,是的,事实就是如此。因此,我们需要在POM.xml中加入jar。

    <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系列的浏览器都能够抛出异常并继续执行异常处理的方法体。

 

 

 

 

 

 

© 著作权归作者所有

HappyBKs

HappyBKs

粉丝 665
博文 306
码字总数 481268
作品 0
浦东
程序员
私信 提问
Spring Boot学习笔记

多模块开发 [SpringBoot学习]-IDEA创建Gradle多Module结构的SpringBoot项目 RabbitMQ RabbitMQ 安装 linux安装RabbitMQ详细教程 Ubuntu 16.04 RabbitMq 安装与运行(安装篇) ubantu安装...

OSC_fly
2018/07/26
0
0
Spring实战读书笔记(1)

Spring的根本使命是? 简化Java开发 为了降低Java开发的复杂性,Spring采取了哪4种关键策略? 1、基于POJO的轻量级和最小侵入性编程 2、通过依赖注入和面向接口实现松耦合 3、基于切面和惯例...

祥林会跟你远走高飞
2014/12/30
446
0
Spring Boot Banner自定义,让你的应用与众不同

点击上方 IT牧场 ,选择 置顶或者星标技术干货每日送达! TIPS 本文基于Spring Boot 2.1.4,理论支持Spring Boot所有版本。 相信玩过Spring Boot的童鞋一定在启动日志中见过类似如下的内容。...

IT牧场
05/08
0
0
SpringBoot | 第十七章:web应用开发之文件上传

前言 上一章节,我们讲解了利用实现前端页面渲染,从而实现动态网页的功能,同时也提出了兼容项目的解决方案。既然开始讲解web开发了,我们就接着继续往这个方向继续吧。通常,我们在做开发时...

oKong
2018/08/08
997
0
spring boot整合dubbo

github: https://github.com/Athlizo/spring-dubbo-parent 码云: https://git.oschina.net/null5843382/spring-dubbo-parent 相关文档: Spring Dubbo 开发笔记(一)——概述: Spring Dub......

lizo
2017/03/01
1K
6

没有更多内容

加载失败,请刷新页面

加载更多

500行代码,教你用python写个微信飞机大战

这几天在重温微信小游戏的飞机大战,玩着玩着就在思考人生了,这飞机大战怎么就可以做的那么好,操作简单,简单上手。 帮助蹲厕族、YP族、饭圈女孩在无聊之余可以有一样东西让他们振作起来!...

上海小胖
今天
8
0
关于AsyncTask的onPostExcute方法是否会在Activity重建过程中调用的问题

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/XG1057415595/article/details/86774575 假设下面一种情况...

shzwork
今天
7
0
object 类中有哪些方法?

getClass(): 获取运行时类的对象 equals():判断其他对象是否与此对象相等 hashcode():返回该对象的哈希码值 toString():返回该对象的字符串表示 clone(): 创建并返此对象的一个副本 wait...

happywe
今天
6
0
Docker容器实战(七) - 容器中进程视野下的文件系统

前两文中,讲了Linux容器最基础的两种技术 Namespace 作用是“隔离”,它让应用进程只能看到该Namespace内的“世界” Cgroups 作用是“限制”,它给这个“世界”围上了一圈看不见的墙 这么一...

JavaEdge
今天
8
0
文件访问和共享的方法介绍

在上一篇文章中,你了解到文件有三个不同的权限集。拥有该文件的用户有一个集合,拥有该文件的组的成员有一个集合,然后最终一个集合适用于其他所有人。在长列表(ls -l)中这些权限使用符号...

老孟的Linux私房菜
今天
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部