春のMaxUploadSizeExceededException

SpringのMaxUploadSizeExceededException

1. 概要

Springフレームワークでは、アプリケーションが構成で指定された特定のしきい値を超えるサイズのファイルをアップロードしようとすると、MaxUploadSizeExceededExceptionがスローされます。

このチュートリアルでは、最大アップロードサイズを指定する方法を見ていきます。 次に、単純なファイルアップロードコントローラーを示し、この例外を処理するさまざまな方法について説明します。

2. 最大アップロードサイズの設定

デフォルトでは、アップロードできるファイルのサイズに制限はありません。 最大アップロードサイズを設定するには、タイプMultipartResolverのBeanを宣言する必要があります。

ファイルサイズを5MBに制限する例を見てみましょう。

@Bean
public MultipartResolver multipartResolver() {
    CommonsMultipartResolver multipartResolver
      = new CommonsMultipartResolver();
    multipartResolver.setMaxUploadSize(5242880);
    return multipartResolver;
}

3. ファイルアップロードコントローラー

次に、ファイルのサーバーへのアップロードと保存を処理するコントローラーメソッドを定義しましょう。

@RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
public ModelAndView uploadFile(MultipartFile file) throws IOException {

    ModelAndView modelAndView = new ModelAndView("file");
    InputStream in = file.getInputStream();
    File currDir = new File(".");
    String path = currDir.getAbsolutePath();
    FileOutputStream f = new FileOutputStream(
      path.substring(0, path.length()-1)+ file.getOriginalFilename());
    int ch = 0;
    while ((ch = in.read()) != -1) {
        f.write(ch);
    }

    f.flush();
    f.close();

    modelAndView.getModel().put("message", "File uploaded successfully!");
    return modelAndView;
}

ユーザーが5MBを超えるサイズのファイルをアップロードしようとすると、アプリケーションはタイプMaxUploadSizeExceededExceptionの例外をスローします。

4. MaxUploadSizeExceededExceptionの処理

この例外を処理するために、コントローラーにインターフェースHandlerExceptionResolverを実装させるか、@ControllerAdviceアノテーション付きクラスを作成することができます。

4.1. HandlerExceptionResolverの実装

HandlerExceptionResolverインターフェースは、異なるタイプの例外を処理できるresolveException()と呼ばれるメソッドを宣言します。

キャッチされた例外のタイプがMaxUploadSizeExceededExceptionの場合にメッセージを表示するには、resolveException()メソッドをオーバーライドしてみましょう。

@Override
public ModelAndView resolveException(
  HttpServletRequest request,
  HttpServletResponse response,
  Object object,
  Exception exc) {

    ModelAndView modelAndView = new ModelAndView("file");
    if (exc instanceof MaxUploadSizeExceededException) {
        modelAndView.getModel().put("message", "File size exceeds limit!");
    }
    return modelAndView;
}

4.2. コントローラーアドバイスインターセプターの作成

コントローラ自体ではなくインターセプタを介して例外を処理することには、いくつかの利点があります。 1つは、同じ例外処理ロジックを複数のコントローラーに適用できることです。

もう1つは、処理する例外のみを対象とするメソッドを作成できることです。これにより、フレームワークは、instanceofを使用してスローされた例外のタイプを確認しなくても、例外処理を委任できます。

@ControllerAdvice
public class FileUploadExceptionAdvice {

    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public ModelAndView handleMaxSizeException(
      MaxUploadSizeExceededException exc,
      HttpServletRequest request,
      HttpServletResponse response) {

        ModelAndView modelAndView = new ModelAndView("file");
        modelAndView.getModel().put("message", "File too large!");
        return modelAndView;
    }
}

5. Tomcatの構成

Tomcatサーバーバージョン7以降にデプロイする場合は、maxSwallowSizeという構成プロパティがあり、設定または変更する必要があります。

このプロパティは、サーバーがファイルを無視することがわかっているときに、クライアントからのアップロードに対してTomcatが「飲み込む」最大バイト数を指定します。

プロパティのデフォルト値は2097152(2 MB)です。 変更しない場合、またはMultipartResolverで設定した5 MBの制限を下回る場合、Tomcatは2 MBを超えるファイルのアップロードを拒否し、カスタム例外処理が呼び出されることはありません。

リクエストが成功し、アプリケーションからのエラーメッセージが表示されるようにするには、maxSwallowSizeプロパティを負の値に設定する必要があります。 これにより、Tomcatは、ファイルサイズに関係なく、失敗したすべてのアップロードを飲み込みます。

これはTOMCAT_HOME/conf/server.xmlファイルで行われます:

6. 結論

この記事では、Springで最大ファイルアップロードサイズを構成する方法と、クライアントがこのサイズ制限を超えるファイルをアップロードしようとしたときに発生するMaxUploadSizeExceededExceptionを処理する方法を示しました。

この記事の完全なソースコードはGitHub projectにあります。