web-dev-qa-db-fra.com

Comment gérer MaxUploadSizeExceededException

Une exception MaxUploadSizeExceededException apparaît lorsque je télécharge un fichier dont la taille dépasse le maximum autorisé. Je souhaite afficher un message d'erreur lorsque cette exception apparaît (comme un message d'erreur de validation). Comment puis-je gérer cette exception pour faire quelque chose comme ça au printemps 3?

Merci.

27
Javi

J'ai finalement trouvé une solution qui fonctionne à l'aide d'un HandlerExceptionResolver.

Ajouter un résolveur en plusieurs parties à votre configuration Spring :

<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>   

Modèle - 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;
    }

}

Vue - /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>

Contrôleur - 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);
    }

}

========================================================================
32
Steve Davis

Merci d'avoir résolu ce Steve. Je me suis mis à essayer pendant plusieurs heures.

La clé est que le contrôleur implémente HandlerExceptionResolver et ajoute la méthode resolveException.

--Bob

6
BobC

Utiliser les conseils du contrôleur

@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;
    }
}
5
Jonghee Park

si vous utilisez ajax, devez répondre json, pouvez répondre json dans la méthode resolException

@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;
  }
1
janwen

C'est une vieille question donc je l'ajoute aux futures personnes (y compris future moi) qui luttent pour que cela fonctionne avec Spring Boot 2 .

Au début, vous devez configurer l’application Spring (dans le fichier de propriétés):

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

Si vous utilisez Tomcat intégré (et le plus probablement, comme il est livré en standard), il est également important de configurer Tomcat pour ne pas annuler la demande avec un corps volumineux.

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

ou au moins le régler sur une taille relativement grande

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

Si vous ne définissez pas maxSwallowSize pour Tomcat, vous risquez de perdre de nombreuses heures à déboguer, mais le navigateur n'obtient aucune réponse. En effet, sans cette configuration, Tomcat annulera la demande et, même si vous verrez dans les journaux cette application traite l'erreur, le navigateur a déjà reçu l'annulation de la demande de Tomcat et n'écoute plus la réponse.

Et pour gérer le MaxUploadSizeExceededException vous pouvez ajouter ControllerAdvice avec ExceptionHandler

Voici un exemple rapide dans Kotlin qui définit simplement un attribut flash avec une erreur et redirige vers une page:

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

REMARQUE: si vous souhaitez gérer MaxUploadSizeExceededException avec ExceptionHandler directement dans votre classe de contrôleur, vous devez configurer la propriété suivante:

spring.servlet.multipart.resolve-lazily=true

sinon, cette exception sera déclenchée avant que la demande ne soit mappée sur le contrôleur.

0
WallTearer