SAStrutsでHTML5の複数ファイルアップロードを行う

HTML5で<input type="file" />multiple属性が追加され、ブラウザのファイル選択画面で複数のファイルが一度に選択でき、サーバへの送信も一度にできるようになった。
SAStrutsはHTML5時代に作られたものではないので、ActionFormでのファイル受取はファイルが一つしか来ないものとして実装されている。フレームワーク部分を拡張してファイルを複数受け取れるようにする。

jspとActionForm

sample.jsp

SampleForm.java

ファイルを受け取る箇所は、FormFileの配列にする。

S2MultipartRequestHandler

リクエスト内容をActionFormに詰めるための前処理としてリクエスト内容の分解と解釈を、SAStrutsで用意されているS2MultipartRequestHandlerクラスが行っている。addTextParameteraddFileParameterというメソッドで、それぞれリクエストの文字列とファイルをActionFormに詰めるための前処理を行っている。文字列のほうは配列に対応できるように全て配列として扱っているのだが、ファイルの方は単体としてしか扱っていないため、addTextParameterを参考にしてaddFileParameterをOverrideする。

S2RequestProcessor

S2RequestProcessorは、数あるActionのうち何を使うか等を解決し、processActionPerformメソッドで実際にActionのメソッドを呼び出す。SAStrutsでの基幹部分となるクラスだ。
S2MultipartRequestHandlerS2RequestProcessorprocessPopulateメソッドに呼び出されている。このメソッドの終盤でsetPropertyメソッドが呼ばれ、ActionFormの各変数にS2MultipartRequestHandlerで前処理された値をセットしている。

S2MultipartRequestHandler#addFileParameterをOverrideしたため、S2RequestProcessor#setProperty内においても、FormFileを単体として扱っていたものが配列として扱わなければいけなくなった。setPropertyで実際に値をセットしている箇所は次の三つのメソッドに切り出されている。

  • setSimpleProperty
  • setMapProperty ※setSimplePropertyから呼ばれる
  • setIndexedProperty

これらのメソッドでString配列がどのように処理されているのかを確認し、String[]の処理と同様にFormFile[]の処理を実装するようOverrideする。
継承したクラスとOverrideしたメソッドは以下の通り。既存の処理にelse if (value instanceof FormFile[])を追加している。
※setIndexedPropertyについては、String[]の処理は行われていないため、Overrideしていない。

※ActionForm内でFormFileを配列で定義しているときは、S2MultipartRequestHandlerの拡張をするだけでも動くのだが、FormFileを単体で定義すると動かなくなってしまう。上に書いた拡張を行えば単体でも動く。

struts-config.xml

S2MultipartRequestHandlerS2RequestProcessorstruts-config.xmlcontrollerタグで設定することになっているが、独自クラスを継承して作ったため、明示的に設定が必要になる。

processorClassmultipartClassにそれぞれ継承実装したクラスを設定しているのは見ての通りとして、maxFileSizeについては注意が必要となる。
maxFileSizeはアップロードされるファイルのサイズを制限する数値だが、ファイルを複数アップロードした時はファイル一つ一つに制限値が適用されるのではなく、複数まとめたサイズに対して適用される。
ファイルを一つだけアップロードした時には十分だった値も、ファイルを複数アップロードするとなると途端に制限が厳しすぎるということになりかねないので、適切な値に設定し直す必要がある。

-Java
-