web-dev-qa-db-ja.com

MaxUploadSizeExceededExceptionの処理方法

許容される最大サイズを超えるサイズのファイルをアップロードすると、MaxUploadSizeExceededException例外が表示されます。この例外が発生したときにエラーメッセージを表示したい(検証エラーメッセージのように)。この例外を処理して、Spring 3でこのようなことをするにはどうすればよいですか?

ありがとう。

28
Javi

最後に、HandlerExceptionResolverを使用して機能するソリューションを見つけました。

マルチパートリゾルバーを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>   

モデル-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;
    }

}

表示-/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:パッケージ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);
    }

}

========================================================================
33
Steve Davis

このスティーブを解決してくれてありがとう。私は数時間解決しようとしてぶらつきました。

重要なのは、コントローラーにHandlerExceptionResolverを実装させ、resolveExceptionメソッドを追加することです。

- ボブ

7
BobC

コントローラーのアドバイスを使用する

@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

これは古い質問なので、これをSpring Boot 2で機能させるのに苦労している将来の人々(将来の私を含む)のために追加します。

最初に、Springアプリケーションを(プロパティファイルで)構成する必要があります。

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

組み込みのTomcatを使用している場合(そして標準として提供されている可能性が高いため)、Tomcatが大きな本文でリクエストをキャンセルしないように構成することも重要です。

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

または、少なくとも比較的大きなサイズに設定します

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

TomcatのmaxSwallowSizeを設定しない場合、エラーが処理された理由をデバッグするのに何時間も費やす可能性がありますが、ブラウザーが応答を返さないことがあります。はエラーを処理しています。ブラウザはすでにTomcatからのリクエストのキャンセルを受信して​​おり、応答をリッスンしていません。

そしてMaxUploadSizeExceededExceptionを処理するためにControllerAdviceExceptionHandlerで追加できます。

以下はKotlinの簡単な例で、フラッシュ属性にエラーを設定し、いくつかのページにリダイレクトします。

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

注:ExceptionHandlerを使用してMaxUploadSizeExceededExceptionをコントローラークラスで直接処理する場合は、次のプロパティを構成する必要があります。

spring.servlet.multipart.resolve-lazily=true

そうでない場合、その例外は、リクエストがコントローラーにマップされる前にトリガーされます。

4
WallTearer

ajaxを使用している場合、jsonに応答する必要があり、resolveExceptionメソッドでjsonに応答できます

@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