【问题标题】:How to handle Multipart Exception如何处理多部分异常
【发布时间】:2017-11-01 03:19:06
【问题描述】:

我正在建立一个上传图片的网站。我正在使用 Spring Boot、eureka 和 zuul 代理。我正在尝试限制用户上传图片的大小。当图片超出限制时,它应该返回一些消息,但它会抛出一个MultipartException。问题是我不知道 如何处理它。我在网上找到了很多例子,但没有一个对我有用。我找到了一个带有 servlet 过滤器的示例,但没有运气。我也尝试过ControllerAdvice,但我仍然无法处理它。

@ControllerAdvice
public class ExceptionController {

    @ExceptionHandler(FileUploadBase.FileSizeLimitExceededException.class)
    public String uploadedAFileTooLarge(FileUploadBase.FileSizeLimitExceededException e) {
        return "File upload error";
    }

    @ExceptionHandler(MultipartException.class)
    public String handleFileException(HttpServletRequest request, Throwable ex) {
        return "File upload error";
    }
}

这是 application.yml:

spring:
  http:
    multipart:
      max-file-size: 5Mb
      max-request-size: 10Mb

这是我得到的例外:

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request; nested exception is java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (41464012) exceeds the configured maximum (10485760)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982) ~[spring-webmvc-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872) ~[spring-webmvc-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:648) ~[tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) ~[spring-webmvc-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) ~[tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230) ~[tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) ~[tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:726) ~[tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:471) ~[tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:394) ~[tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:311) ~[tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:395) [tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:254) [tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.catalina.core.StandardHostValve.throwable(StandardHostValve.java:349) [tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:175) [tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349) [tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:784) [tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:802) [tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1410) [tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.6.jar:8.5.6]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_121]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_121]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.6.jar:8.5.6]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_121]
Caused by: org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request; nested exception is java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (41464012) exceeds the configured maximum (10485760)
    at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.parseRequest(StandardMultipartHttpServletRequest.java:111) ~[spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.<init>(StandardMultipartHttpServletRequest.java:85) ~[spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    at org.springframework.web.multipart.support.StandardServletMultipartResolver.resolveMultipart(StandardServletMultipartResolver.java:76) ~[spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.checkMultipart(DispatcherServlet.java:1099) ~[spring-webmvc-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:932) ~[spring-webmvc-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897) ~[spring-webmvc-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) ~[spring-webmvc-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    ... 26 common frames omitted
Caused by: java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (41464012) exceeds the configured maximum (10485760)
    at org.apache.catalina.connector.Request.parseParts(Request.java:2871) ~[tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.catalina.connector.Request.parseParameters(Request.java:3176) ~[tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.catalina.connector.Request.getParameter(Request.java:1110) ~[tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.catalina.connector.RequestFacade.getParameter(RequestFacade.java:381) ~[tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:70) ~[spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) ~[tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) ~[tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) ~[spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) ~[tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) ~[tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:106) ~[spring-boot-actuator-1.4.3.RELEASE.jar:1.4.3.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) ~[tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) ~[tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) ~[tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:108) ~[tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472) ~[tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.6.jar:8.5.6]
    ... 12 common frames omitted
Caused by: org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (41464012) exceeds the configured maximum (10485760)
    at org.apache.tomcat.util.http.fileupload.FileUploadBase$FileItemIteratorImpl.<init>(FileUploadBase.java:811) ~[tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.tomcat.util.http.fileupload.FileUploadBase.getItemIterator(FileUploadBase.java:256) ~[tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.tomcat.util.http.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:280) ~[tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.catalina.connector.Request.parseParts(Request.java:2801) ~[tomcat-embed-core-8.5.6.jar:8.5.6]
    ... 31 common frames omitted

如果需要任何其他信息,我很乐意提供给您。

【问题讨论】:

  • 你能在你的主类中捕捉到那个异常吗?
  • 是的,我已经知道原因了,问题是我不知道如何处理异常。我需要能够从 catch 块返回一条消息并警告用户,他应该上传一张较小的图片
  • 不,我无法抓住它:(
  • 我认为您需要创建一个自定义异常处理程序类,然后将其传递给处理文件上传的类的@ExceptionHandler 注释。在该类中,您将能够检查异常的类型,然后使用代码来提醒用户。
  • 它是SizeLimitExceededException 你能增加你的多部分文件大小

标签: java spring-boot netflix-eureka netflix-zuul


【解决方案1】:

我发现你可以处理的异常是 java.lang.IllegalStateException。不抛出 FileUploadBase.FileSizeLimitExceededException.class。也许是因为它是一个内部类?

为了让它工作,我还必须对 Tomcat 的 server.xml 进行更改。

Tomcat 的默认行为是断开发送(上传)过多数据的客户端。连接关闭后,您将无法向客户端发送任何数据。

您可以通过将maxSwallowSize = "-1" 添加到 server.xml 中的连接器来指示 Tomcat 继续读取请求,即使请求的大小已超过限制。

有关如何在 Spring 中处理异常的完整详细说明,请参阅:http://www.baeldung.com/spring-maxuploadsizeexceeded

【讨论】:

    【解决方案2】:

    尝试在您的异常处理程序类中添加一个方法,如下所示:

    @ExceptionHandler(MultipartException.class)
    public String handleMultipartException(MultipartException e, RedirectAttributes redirectAttributes) {
        redirectAttributes.addFlashAttribute("message", e.getCause().getMessage());
        return "redirect:/uploadStatus";
    }
    

    您可以有另一个页面来显示上传状态,如下所示:

    <html>
    <body>
    <h1>Upload Status</h1>
    <h2>Message : ${message}</h2>
    </body>
    </html>
    

    here 提供了更多详细信息。

    【讨论】:

    • 不,很遗憾,这并没有解决问题。我得到了同样的异常,但仍然无法捕捉到它。我怀疑在请求到达调度程序 servlet 之前抛出异常。因此没有调用异常处理程序,因为在抛出异常时目标控制器尚未确定
    • 您确定异常没有到达 ExceptionHandler 吗?尝试添加一个 sysout 并检查它是否在控制台中打印,这样我们就可以确定异常没有到达处理程序。
    • 还要确保您的异常处理程序包含在组件扫描包中。
    • 我尝试在控制台中打印,但没有打印出来。我还在 ExceptionHandler 中添加了一个断点,但它没有到达
    • 我认为异常处理程序没有配置为组件扫描。异常处理程序类是否捕获了其他抛出的异常?尝试抛出一个不同的异常,你在异常处理程序中处理它,看看它是否被捕获?然后,您可以确认您的处理程序类是否未配置组件扫描。
    猜你喜欢
    • 1970-01-01
    • 2016-03-06
    • 2021-02-06
    • 1970-01-01
    • 1970-01-01
    • 2021-05-22
    • 2018-03-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多