6.2.9. マルチパートリクエストハンドラ

HTTPリクエストがマルチパート形式の場合に、ボディ部を解析しアップロードファイルを一時ファイルとして保存するハンドラ。

本ハンドラでは、以下の処理を行う。

  • マリチパートリクエストの解析
  • アップロードファイルを一時ファイルとして保存
  • 保存した一時ファイルの削除

処理の流れは以下のとおり。

../../../../_images/flow36.png

6.2.9.2. モジュール一覧

<dependency>
  <groupId>com.nablarch.framework</groupId>
  <artifactId>nablarch-fw-web</artifactId>
</dependency>

<!-- 一時保存先を指定する場合のみ -->
<dependency>
  <groupId>com.nablarch.framework</groupId>
  <artifactId>nablarch-core</artifactId>
</dependency>

6.2.9.3. 制約

なし。

6.2.9.4. このハンドラの動作条件

このハンドラはマルチパート形式のリクエストの場合のみ、リクエストボディの解析を行う。マルチパート形式かどうかは、リクエストヘッダーの Content-Type で判断する。

Content-Typemultipart/form-data と一致する場合は、リクエストがマルチパート形式だと判断し、ボディの解析処理を行う。 それ以外の場合には、このハンドラは何もせずに後続のハンドラに処理を委譲する。

6.2.9.5. アップロードファイルの一時保存先を指定する

アップロードファイルの一時保存先ディレクトリは、 ファイルパス管理 に設定する。

ファイルパス管理に一時保存先ディレクトリの指定がない場合は、デフォルトの保存先としてシステムプロパティの java.io.tmpdir の値を使用する。

以下に一時ファイルの保存先ディレクトリの設定例を示す。

ポイント
  • 保存先ディレクトリの論理名は、 uploadFileTmpDir とすること。
<component name="filePathSetting" class="nablarch.core.util.FilePathSetting">
  <!-- ディレクトリの設定 -->
  <property name="basePathSettings">
    <map>
      <!-- アップロードファイルの一時保存ディレクトリ -->
      <entry key="uploadFileTmpDir" value="file:/var/nablarch/uploadTmpDir" />
    </map>
  </property>
</component>

補足

上記の例では、保存先ディレクトリを直接指定しているが、この値は環境ごとに異なることが想定される。 このため、直接コンポーネント設定ファイルに設定するのではなく、環境設定ファイルに設定することを推奨する。

詳細は、依存値を設定する を参照。

6.2.9.6. 巨大なファイルのアップロードを防ぐ

巨大なファイルをアップロードされると、ディスクリソースが枯渇するなどが原因でシステムが正常に稼働しなくなる可能性がある。 このため、このハンドラではアップロードサイズの上限を超過した場合には、400(BadRequest)をクライアントに返却する。

アップロードサイズの上限は、バイト数で設定する。設定を省略した場合は、無制限となる。

以下にアップロードサイズの設定例を示す。

<component class="nablarch.fw.web.upload.MultipartHandler" name="multipartHandler">
  <property name="uploadSettings">
    <component class="nablarch.fw.web.upload.UploadSettings">
      <!-- アップロードサイズ(Content-Length)の上限(約10M) -->
      <property name="contentLengthLimit" value="1000000" />
    </component>
  </property>
</component>

補足

アップロードサイズの上限は、ファイル単位ではなく1リクエストでアップロード出来る上限となる。

このため、複数のファイルをアップロードした場合には、それらのファイルサイズの合計値(厳密には、Content-Length)により、上限チェックが実施される。

もし、ファイル単位でサイズチェックをする必要がある場合には、アクション側で実装すること。

6.2.9.7. 一時ファイルの削除(クリーニング)を行う

保存されたアップロードファイルを以下の条件でクリーニングする。

  • ボディの解析中に例外が発生した場合
  • ハンドラの復路で自動削除設定が有効な場合

自動削除設定は、デフォルトで有効に設定されている。 この設定は本番環境で安易に無効にすると、大量の一時ファイルがディスク上に残り、最悪の場合ディスクフルの原因となるため注意すること。

設定値を無効にする場合には、 UploadSettings#autoCleaningfalse を設定する。

6.2.9.8. マルチパート解析エラー及びファイルサイズ上限超過時の遷移先画面を設定する

このハンドラでは、マルチパート解析エラー [1]ファイルサイズの上限超過時 に、 不正なリクエストとしてクライアントに 400(BadRequest) を返却する。

このため、 400(BadRequest) に対応したエラーページの設定を web.xml に行う必要がある。 web.xml へのエラーページ設定を省略した場合は、ウェブアプリケーションサーバが持つデフォルトのページなどがクライアントに返却される。

重要

このハンドラは、制約 にあるとおり、 セッション変数保存ハンドラ より手前に設定する必要がある。 このため、 セッション変数保存ハンドラ の後続に設定される HTTPエラー制御ハンドラデフォルトページの設定 は使用することができない。

[1]

マルチパート解析エラーが発生するケース

  • アップロード中にクライアントからの切断要求があり、ボディー部が不完全な場合
  • バウンダリーが存在しない

6.2.9.9. アップロードしたファイルを読み込む

アップロードされたファイル(一時保存されたファイル)は、 HttpRequest から取得する。

以下に実装例を示す。

ポイント
public HttpResponse upload(HttpRequest request, ExecutionContext context) throws IOException {
  // アップロードファイルの取得
  List<PartInfo> partInfoList = request.getPart("uploadFile");

  if (partInfoList.isEmpty()) {
    // アップロードファイルが指定されていなかった場合は業務エラー
  }

  // アップロードされたファイルを処理する
  InputStream file = partInfoList.get(0).getInputStream()

  // 以下アップロードファイルを読み込み処理を行う。
}

アップロードファイルを処理する詳細な実装方法は、以下のドキュメントを参照。 なお、 様々なフォーマットのデータへのアクセス に記載がある通り、 データバインド が推奨となる。 (データバインド で扱うことのできない形式の場合は、 汎用データフォーマット を使用すること。)

補足

アップロードされたファイルが画像ファイル等のバイナリファイルの場合は、読み込んだバイナリデータを使用して処理を行うこと。

Java8であれば以下の様に実装することでアップロードファイルのバイトデータを読み込むことができる。

File savedFile = partInfo.getSavedFile();
try {
    byte[] bytes = Files.readAllBytes(savedFile.toPath());
} catch (IOException e) {
    throw new RuntimeException(e);
}