クライアントのファイルをサーバにアップロードすることができます。 アップロードされたファイルは com.fujitsu.uji.util.MimeSourceクラスから取り出すことができます。
例として、以下のような画面を作成します。

"参照"ボタンを押すと、クライアント側のファイル選択ダイアログが出力されます。
"アップロード"ボタンを押すと、filenameで示されるファイルがサーバへアップロードされます。
以下の3つの定義が必要です。
定義場所 | 定義内容 |
|---|---|
1. 入出力ページ(JSP) | 送信するファイルの指定と送信ボタンの追加 |
2. データBean | 送信されたファイルを受け取るMimeSource型のプロパティを追加 |
3. ビジネスロジック | 送信されたファイルをMimeSourceクラスから取得する処理を追加 |
1. 入出力ページ(JSP)
以下の3つの定義を追加します。
1.1 uji:formタグのenctypeアトリビュート指定
uji:formタグには、enctype="multipart/form-data"アトリビュートを指定します。
<uji:form method="post" name="mainForm" enctype="multipart/form-data" beanId="body" beanCls="upfile.BodyBean" verbs="upload" >
....
</uji:form>1.2 "参照"ボタン付の入力領域
INPUTタグのtype="FILE"アトリビュートは、フォームのデータとして送信するファイル を選択するボタンと入力域を表します。
name="file"で示されるのは、サーバでファイルを受け取るプロパティの名前と対応しています。
詳細は“2. データBean”を参照してください。
<INPUT type="FILE" name="file" />1.3 サーバへの送信ボタン
サーバへの送信ボタンをINPUTタグで作成します。 この例ではボタンを押すと"upload"というコマンドを発行しています。 コマンドは、INPUTタグのnameアトリビュートに指定しています。
<uji:form method="post" name="mainForm" enctype="multipart/form-data" beanId="body" beanCls="upfile.BodyBean" verbs="upload" >
....
<INPUT type="submit" name="upload" value="アップロード">最終的に作成されるJSPは以下のようになります。
<%@ page contentType="text/html; charset=shift_jis" %> <%@ taglib uri="uji-taglib" prefix="uji" %> <uji:useBean id="body" cls="upfile.BodyBean" request="true" /> <uji:form method="post" name="mainForm" enctype="multipart/form-data" beanId="body" beanCls="upfile.BodyBean" verbs="upload" > <uji:controlState/> <INPUT type="FILE" name="file"/><BR>
<INPUT type="submit" name="upload" value="アップロード" > </uji:form>
2. データBean
送信されたファイルを受け取るMimeSource型のプロパティを追加します。
このプロパティの名前は、“1.2 "参照"ボタン付の入力領域”で指定したプロパティと対応しています。
import com.fujitsu.uji.DataBean;
import com.fujitsu.uji.util.MimeSource;
public class BodyBean extends DataBean
{
protected MimeSource file;
public MimeSource getFile() {
return file;
}
public void setFile(MimeSource file) {
this.file = file;
}
}3. ビジネスロジック
送信されたファイルをMimeSourceクラスから取得する処理を追加します。
以下の4つの処理を追加します。
3.1 データBeanから、MimeSourceの取得
データBeanから、MimeSource型のプロパティを取得します。
MimeSource source=dataBean.getFile();
3.2 MimeSourceから、InputStreamとファイル名の取得
MimeSourceから、InputStreamと送信されたファイル名を取得します。 それぞれ、変数is, fnameへ格納しています。
InputStream is = source.getInputStream(); String fname = source.getFileName();
3.3 InputStreamから、アップロードされたファイルの読み込み
InputStreamからアップロードされたファイルを読み込みます。 この例では、サーバのフォルダにファイルとして書き出します。
// 格納するサーバのフォルダを求めます。
// ここでは、アプリケーションの配置と同じフォルダとします。
String name = "/";
if(context instanceof HttpDispatchContext) {
ServletContext svc = ((HttpDispatchContext)context).getServletContext();
name = svc.getRealPath(name);
}
// 格納するファイル名を決定します。
File savename = new File(getRealFolder(context), fname);
// 実際にファイルへ書き出します。
try {
FileOutputStream os = new FileOutputStream(savename);
byte buffer[] = new byte[1024];
int size;
while((size = is.read(buffer)) > 0)
os.write(buffer, 0, size);
os.close();
} catch(Exception e) {
e.printStackTrace();
}3.4 リソースを解放可能にするためプロパティにnullを設定
アップロードの処理が終了したら、MimeSource型のプロパティにnullを設定します。このようにしてMimeSourceへの参照を削除することにより、ガーベジコレクタがMimeSourceを破棄できるようになります。MimeSourceが破棄された時点でリソースが解放されます。
dataBean.setFile(null);
最終的に作成されるJSPは以下のようになります。
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import javax.servlet.ServletContext;
import com.fujitsu.uji.util.MimeSource;
import com.fujitsu.uji.GenericHandler;
import com.fujitsu.uji.DispatchContext;
import com.fujitsu.uji.http.HttpDispatchContext;
....
public class UploadHandler extends GenericHandler {
public void upload(DispatchContext context, BodyBean dataBean) {
MimeSource source=dataBean.getFile();
InputStream is = source.getInputStream();
String fname = source.getFileName();
// 格納するサーバのフォルダを求めます。
// ここでは、アプリケーションの配置と同じフォルダとします。
String name = "/";
if(context instanceof HttpDispatchContext) {
ServletContext svc = ((HttpDispatchContext)context).getServletContext();
name = svc.getRealPath(name);
}
// 格納するファイル名を決定します。
File savename = new File(getRealFolder(context), fname);
// 実際にファイルへ書き出します。
try {
FileOutputStream os = new FileOutputStream(savename);
byte buffer[] = new byte[1024];
int size;
while((size = is.read(buffer)) > 0)
os.write(buffer, 0, size);
os.close();
} catch(Exception e) {
e.printStackTrace();
}
dataBean.setFile(null);
....
}
....
}4. アップロードファイルの定量制限について
ファイルをアップロードする場合には、以下の定量制限があります。
アップロードヘッダ長は1024バイト以内です。
アップロードヘッダには、項目名とファイル名の情報が含まれます。利用するブラウザによって多少異なりますが、項目名長とファイル名長を合わせて、970バイト程度を指定可能です。
アップロードファイルサイズの上限はデフォルトで16MB (16*1024*1024バイト)です。このサイズは、アプリケーションクラスでgetMimeTransferSizeLimitメソッドをオーバライドすることで変更できます。getMimeTransferSizeLimitメソッドの詳細は、“17.2 バイナリファイルの送受信”を参照してください。
これらの定量制限を超えた場合は、IOException例外が発生します。発生した例外はDispatchExceptionクラスでラップされ、セションクラスに実装したhandleExceptionメソッド、アプリケーションクラスに実装したhandleExceptionメソッドに通知されます。なお、handleExceptionメソッドを使用するには、Postprocessorインタフェースをセションクラスまたはアプリケーションクラスに実装する必要があります。 handleExceptionメソッドの使用方法については、“4.2 エラー処理”を参照してください。
以下は、セションクラスのhandleExceptionメソッドで、アップロードヘッダ長が制限を越えた場合の例外を受け取る例です。
import com.fujitsu.uji.http.HttpControlStateProfile;
import com.fujitsu.uji.DispatchContext;
import com.fujitsu.uji.log.NestedException;
import com.fujitsu.uji.DispatchException;
public class UpdownSession extends HttpControlStateProfile {
public Object handleException(DispatchContext context, Throwable th) throws Throwable {
if (th instanceof DispatchException) {
Throwable rootCause = th;
// 原因となった例外を取得します。
while(rootCause instanceof NestedException) {
rootCause = ((NestedException)rootCause).getRootCause();
}
String errorMessage = rootCause.getMessage();
if (errorMessage != null && errorMessage.startsWith("UJI075:")) {
// エラーメッセージが "UJI075:" で始まっていれば ヘッダデータ長が
// 制限を越えた場合の例外だと判断します。
// 以下でアップロードヘッダ長が制限を越えた時の処理を実行します。
....
} else {
// それ以外の例外の処理です。
....
// このメソッドで処理しない場合は、throw文を使って例外を
// 再度スローします。
// throw th;
}
} else {
// DispatchException以外の例外の処理です。
....
// このメソッドで処理しない場合は、throw文を使って例外を再度スローします。
// throw th;
}
return null;
}
}関連項目