How to handle MaxUploadSizeExceededException

前端 未结 5 514
小鲜肉
小鲜肉 2020-11-29 22:52

MaxUploadSizeExceededException exception appears when I upload a file whose size exceeds the maximum allowed. I want to show an error message when this exceptio

相关标签:
5条回答
  • 2020-11-29 23:33

    This is an old question so I'm adding it for the future people (including future me) who are struggling to get this working with Spring Boot 2.

    At first you need to configure the spring application (in properties file):

    spring.servlet.multipart.max-file-size=10MB
    spring.servlet.multipart.max-request-size=10MB
    

    If you're using embedded Tomcat (and most likely you are, as it comes as standard) it's also important to configure Tomcat not to cancel the request with large body

    server.tomcat.max-swallow-size=-1
    

    or at least set it to relatively big size

    server.tomcat.max-swallow-size=100MB
    

    If you will not set maxSwallowSize for Tomcat, you might waste lots of hours debugging why the error is handled but browser gets no response - that's because without this configuration Tomcat will cancel the request, and even though you'll see in the logs that application is handling the error, the browser already received cancellation of request from Tomcat and isn't listening for the response anymore.

    And to handle the MaxUploadSizeExceededException you can add ControllerAdvice with ExceptionHandler.

    Here's a quick example in Kotlin that simply sets a flash attribute with an error and redirects to some page:

    @ControllerAdvice
    class FileSizeExceptionAdvice {
        @ExceptionHandler(MaxUploadSizeExceededException::class)
        fun handleFileSizeException(
            e: MaxUploadSizeExceededException, 
            redirectAttributes: RedirectAttributes
        ): String {
            redirectAttributes.addFlashAttribute("error", "File is too big")
            return "redirect:/"
        }
    }
    

    NOTE: if you want to handle MaxUploadSizeExceededException with ExceptionHandler directly in your controller class, you should configure following property:

    spring.servlet.multipart.resolve-lazily=true
    

    otherwise that exception will be triggered before the request is mapped to controller.

    0 讨论(0)
  • 2020-11-29 23:38

    Use controller advice

    @ControllerAdvice
    public class GlobalExceptionHandler {
    
        @ExceptionHandler(MaxUploadSizeExceededException.class)
        public ModelAndView handleMaxUploadException(MaxUploadSizeExceededException e, HttpServletRequest request, HttpServletResponse response){
            ModelAndView mav = new ModelAndView();
            boolean isJson = request.getRequestURL().toString().contains(".json");
            if (isJson) {
                mav.setView(new MappingJacksonJsonView());
                mav.addObject("result", "nok");
            }
            else mav.setViewName("uploadError");
            return mav;
        }
    }
    
    0 讨论(0)
  • 2020-11-29 23:39

    I finally figured out a solution that works using a HandlerExceptionResolver.

    Add multipart resolver to your Spring config:

    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">    
       <!--  the maximum size of an uploaded file in bytes -->
       <!-- <property name="maxUploadSize" value="10000000"/> -->
       <property name="maxUploadSize" value="1000"/>
    </bean>   
    

    Model - UploadedFile.java:

    package com.mypkg.models;
    
    import org.springframework.web.multipart.commons.CommonsMultipartFile;
    
    public class UploadedFile
    {
        private String title;
    
        private CommonsMultipartFile fileData;
    
        public String getTitle()
        {
            return title;
        }
    
        public void setTitle(String title)
        {
            this.title = title;
        }
    
        public CommonsMultipartFile getFileData()
        {
            return fileData;
        }
    
        public void setFileData(CommonsMultipartFile fileData)
        {
            this.fileData = fileData;
        }
    
    }
    

    View - /upload.jsp:

    <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
    <%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
    <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <html>
        <head>
            <title>Test File Upload</title>
        </head>
        <body>
            <h1>Select a file to upload</h1>
            <c:if test="${not empty errors}">
                <h2 style="color:red;">${errors}.</h2>
            </c:if>
            <form:form modelAttribute="uploadedFile" method="post" enctype="multipart/form-data" name="uploadedFileform" id="uploadedFileform">
                <table width="600" border="0" align="left" cellpadding="0" cellspacing="0" id="pdf_upload_form">
                    <tr>
                        <td width="180"><label class="title">Title:</label></td>
                        <td width="420"><form:input id="title" path="title" cssClass="areaInput" size="30" maxlength="128"/></td>
                    </tr>
                    <tr>
                        <td width="180"><label class="title">File:</label></td>
                        <td width="420"><form:input id="fileData" path="fileData" type="file" /></td>
                     </tr>
                     <tr>
                        <td width="180"></td>
                        <td width="420"><input type="submit" value="Upload File" /></td>
                     </tr>
                </table>
            </form:form>
        </body>
    </html>
    

    Controller - FileUploadController.java: package com.mypkg.controllers;

    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.HashMap;
    import java.util.Map;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.validation.BindingResult;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.multipart.MaxUploadSizeExceededException;
    import org.springframework.web.servlet.HandlerExceptionResolver;
    import org.springframework.web.servlet.ModelAndView;
    
    import com.mypkg.models.UploadedFile;
    
    @Controller
    public class FileUploadController  implements HandlerExceptionResolver
    {
        @RequestMapping(value = "/upload", method = RequestMethod.GET)
        public String getUploadForm(Model model)
        {
            model.addAttribute("uploadedFile", new UploadedFile());
            return "/upload";
        }
    
        @RequestMapping(value = "/upload", method = RequestMethod.POST)
        public String create(UploadedFile uploadedFile, BindingResult result)
        {
            // Do something with the file
            System.out.println("#########  File Uploaded with Title: " + uploadedFile.getTitle());
            System.out.println("#########  Creating local file: /var/test-file-upload/" + uploadedFile.getFileData().getOriginalFilename());
    
            try
            {
    
                InputStream in = uploadedFile.getFileData().getInputStream();
                FileOutputStream f = new FileOutputStream(
                        "/var/test-file-upload/" + uploadedFile.getFileData().getOriginalFilename());
                int ch = 0;
                while ((ch = in.read()) != -1)
                {
                    f.write(ch);
                }
                f.flush();
                f.close();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
    
            return "redirect:/";
        }
    
        /*** Trap Exceptions during the upload and show errors back in view form ***/
        public ModelAndView resolveException(HttpServletRequest request,
                HttpServletResponse response, Object handler, Exception exception)
        {        
            Map<String, Object> model = new HashMap<String, Object>();
            if (exception instanceof MaxUploadSizeExceededException)
            {
                model.put("errors", exception.getMessage());
            } else
            {
                model.put("errors", "Unexpected error: " + exception.getMessage());
            }
            model.put("uploadedFile", new UploadedFile());
            return new ModelAndView("/upload", model);
        }
    
    }
    
    ========================================================================
    
    0 讨论(0)
  • 2020-11-29 23:42

    if using ajax,need to response json,can response json in resolveException method

    @Override
      public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response,
          Object handler, Exception ex) {
        ModelAndView view = new ModelAndView();
        view.setView(new MappingJacksonJsonView());
        APIResponseData apiResponseData = new APIResponseData();
    
        if (ex instanceof MaxUploadSizeExceededException) {
          apiResponseData.markFail("error message");
          view.addObject(apiResponseData);
          return view;
        }
        return null;
      }
    
    0 讨论(0)
  • 2020-11-29 23:54

    Thanks for solving this Steve. I banged around trying to solve for several hours.

    The key is to have the controller implement HandlerExceptionResolver and add the resolveException method.

    --Bob

    0 讨论(0)
提交回复
热议问题