ファイルのアップロード
概要
Javaのウェブアプリケーションでファイルアップロードを扱うことは、初心者にとって1つの難関となります。 なぜならServletには、このリクエストを統一して扱うためのインターフェースが用意されていないためです。 大抵の場合、ServletRequestのgetParameterメソッドを使ってパラメータを文字列として取り出すことすらできません。
HTMLにファイルアップロードのためのフォームを用意するには、 form要素のenctype属性に"multipart/form-data"を指定します。 以下は、ファイルアップロードフォームの例です。 (labelやinput要素を始めて目にする方は とほほのWWW入門 で勉強してください。)
<form action="upload.act" method="post" enctype="multipart/form-data">
<label for="file">アップロードするファイル:</label>
<input type="file" name="file" id="file">
</form>
このとき、ブラウザはeメールによく似た形式でファイルとリクエストパラメータを送信します。 このデータは普通のリクエストパラメータと全く形式が異なるばかりか、非常に大きなサイズを扱うので、特別な処理を必要とします。 Pastaは、そのためのインターフェースを用意しています。
プログラムの書き方
WebContextのgetParameterメソッドは、 通常のリクエストとmultipart/form-dataリクエストの両方でパラメータが得られることを保証しています。 また、ファイルアップロードはprocessUploadメソッドによって処理します。 ここで注意しなければならないのは、processUploadはgetParameterあるいはgetParameterValuesによってパラメータが取り出される前に呼び出されなければならないことです。 なぜなら、パラメータの解析はgetParameter,getParameterValues,processUploadのいずれかが最初に呼ばれた時点で一括して行われ、 パラメータは保持されますが、ファイルはメモリを圧迫するのを避けるために即座に破棄されるためです。 ファイルをディスクに保管したい場合は、パラメータを取得する前にprocessUploadを呼んで、データをディスクに書き込むプログラムを書く必要があります。
以下は、ファイルアップロードを処理するコードの例です。
webContext.processUpload(new UploadHandler() {
public OutputStream handleFile(String fieldName, String contentType, String fileName) throws IOException {
File file = new File(fileName);
return new BufferedOutputStream(new FileOutputStream(file));
}
});
これで、ユーザーがアップロードしたファイルがディスクに保存されます。 もちろん、実際はファイル名の重複を防ぐような処理が必要になるでしょう。 これらの処理を自動的にせずに、ユーザーに任せている理由は、全てのユーザーがアップロードされたファイルをディスクに保存するとは限らないためです。 例えば、データベースのBLOB型として保存することもあるでしょう。 その場合、一時的にディスクに保存する処理は、サーバーにとって余計な負担となります。

