- PR -

Commons FileUploadでファイル情報を取得できない。

1
投稿者投稿内容
KingSize
常連さん
会議室デビュー日: 2002/11/13
投稿数: 38
投稿日時: 2005-03-24 14:48
こんにちわ。
CommonsのFileUploadを使用してファイルアップロードを行ないたいのですが、うまくいかないので投稿させて頂きました。

環境は以下の通りです。
OS WindowsXP SP1
JDK jdk1.3.1_10
APサーバ WebSphere5.0
フレームワーク cFramework V1.5.5
ファイルアップロードライブラリ commons-fileupload-1.0.jar

ソースは以下の通りです。

画面のHTMLソース
<form method="post" enctype="multipart/form-data" action="ActingInput?ActionType=GoReadFile">
〜〜〜〜省略〜〜〜〜
<input type="file" name="localFilepath" size="25" value="">
<input type="hidden" name="YEARS" value="2006"/>
<input type="submit" name="search" value=" 取込 " class="smallSize">
〜〜〜〜以下省略〜〜〜〜

ファイルアップロードを行なうプログラム

import org.apache.commons.fileupload.DiskFileUpload;
import javax.servlet.http.HttpServletRequest;
〜〜〜〜省略〜〜〜〜
private void selectFileExec(HttpServletRequest request) {
DiskFileUpload objDfu = new DiskFileUpload();

// アップロードファイルの最大サイズ
objDfu.setSizeMax(4000);

// バッファサイズ
objDfu.setSizeThreshold(4000);

// ヘッダの文字エンコーディング
objDfu.setHeaderEncoding("Windows-31J");

InputStream inputStream = null;
InputStreamReader reader = null;
BufferedReader bufferedReader = null;

try {
List objLst = objDfu.parseRequest(request);
〜〜〜〜以下省略〜〜〜〜

上記ソースの最後の行で変数objLstにサイズ0のArrayListが入ってきます。
commons-fileupload-1.0.jarのソースを使用してparseRequest(request)をデバッグで追ってみました。

FileUploadBase#parseRequest(request)の339行目に
boolean nextPart = multi.skipPreamble();
という記述があります。
この中をさらにデバッグしてみました。

org.apache.commons.fileupload.MultipartStream#skipPreamble()の690行目で
同じクラスのdiscardBodyData()を呼び出しています。

このメソッドの中で(ソースの651行目)
bytesRead = input.read(buffer, pad, bufSize - pad);

という記述がありますが、ここでbytesReadで-1が入ってきてしまいます。
その結果MalformedStreamExceptionがスローされ、長さ0のArrayListが返されるようです。
変数inputはjava.io.InputStream型で、
メソッドread(byte[] b, int off, int len)が-1を返すのは「ストリームの終わりに達してデータがない場合」とAPIにあります。
どうしてこうなってしまうのかがわかりません。

同じマシンで
http://www.atmarkit.co.jp/fjava/javatips/106jakarta018.html
のサンプルを試したのですが、こちらはうまくいきました。

違う点はAPサーバ(サンプルを試したときはTomcat5.0)、フレームワークを使っているかどうか、あたりなのですがここに原因があるのでしょうか?

どなたかアドバイスをお願いいたします。
uk
ぬし
会議室デビュー日: 2003/05/20
投稿数: 1155
お住まい・勤務地: 東京都
投稿日時: 2005-03-25 11:46
そのクラスがどのタイミングで呼び出されているのかわかりませんが、フレームワーク側で
リクエスト処理してしまっているために、入力ストリームが終端に達しているのではないで
しょうか。
KingSize
常連さん
会議室デビュー日: 2002/11/13
投稿数: 38
投稿日時: 2005-03-25 14:20
お返事ありがとうございました。

Tomcatで動いていたサンプルをWebアプリケーションとしてWebSphereにデプロイした結果、正常に動作しましたので、uk様の言うとおりフレームワーク側でなんらかの処理を行なっているのだと思います。

入力ストリームが終端に達しているのならば、先頭に戻せばいいのではないかと思うのですが、どのようにして戻せばよいのでしょうか?

InputStream#reset()が該当するのかと思い、
InputStream input = request.getInputStream();
if(input.markSupported()){
input.reset();
}
List objLst = objDfu.parseRequest(request);
としてみたのですが、
input.markSupported()がfalseを返してしまいうまくいきません。

他の方法をWebなどで調べているのですが、良い方法をご存知の方がいらっしゃいましたらご教授をお願いします。
uk
ぬし
会議室デビュー日: 2003/05/20
投稿数: 1155
お住まい・勤務地: 東京都
投稿日時: 2005-03-25 14:27
フレームワーク側でリクエストオブジェクトに対してgetParameter、getReader、getInputStreamなどを呼び出していたら、そのオブジェクトに対して入力ストリームを
取得することはできません。ファイルからの入力とは異なり、ネットワークからの入力
ですので、一度読み出してしまったら再度読み込むことはできないのです。

cFrameworkについては知らないのですが、ファイルアップロードの手段は用意されていない
のでしょうか。
KingSize
常連さん
会議室デビュー日: 2002/11/13
投稿数: 38
投稿日時: 2005-03-25 17:33
お返事ありがとうございました。

フレームワーク関連のソースを見ていたところ、ファイルアップロードを実行している箇所を発見しました。

その処理は私が記述した処理より前に行なわれていたので、掲題の問題が発生していたのだと思います。
その処理によってアップロードファイルがローカルの指定された場所に保存されるので、パスを指定してそのファイルを取得しようと思います。
サーバ側の処理終了時に自動的に削除する処理も実装していたため、ファイルの存在に気づきませんでした。

お騒がせして申し訳ありませんでした。

また、アドバイスをして頂いたuk様には厚くお礼を申し上げます。
ありがとうございました。
1

スキルアップ/キャリアアップ(JOB@IT)