- PR -

Strutsでのファイルアップロード(ファイル数は動的)

1
投稿者投稿内容
ちば
大ベテラン
会議室デビュー日: 2003/02/14
投稿数: 114
お住まい・勤務地: 都内勤務
投稿日時: 2003-12-24 16:21
みなさんこんにちわ。

ただいまStrutsでWebアプリケーションを作成しています。
ブラウザから複数のファイルをアップロードしたいのですが、
色々方法を調べても解決できませんでした。

複数のファイルと言ってもそれは動的に変化します。

知りたいことは、
@JSPでの<html:file 〜 の記述方法
AActionFormクラスでの変数の宣言方法
です。

試した方法
コード:
JSP:
<html:file property="theFile"・・・
<html:file property="theFile"・・・

ActionForm:
private FormFile[] theFile = null;



上記の場合、以下のようなエラーが発生します。

コード:
HTTP Status 500 - 

--------------------------------------------------------------------------------

type Exception report

message 

description The server encountered an internal error () that prevented it from fulfilling this request.

exception 

javax.servlet.ServletException: BeanUtils.populate
	at org.apache.struts.util.RequestUtils.populate(RequestUtils.java:1254)
	at org.apache.struts.action.RequestProcessor.processPopulate(RequestProcessor.java:821)
	at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:254)
	at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1482)
	at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:525)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:760)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:247)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:256)
	at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)
	at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
	at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
	at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)
	at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
	at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
	at org.apache.catalina.core.StandardContext.invoke(StandardContext.java:2416)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:180)
	at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)
	at org.apache.catalina.valves.ErrorDispatcherValve.invoke(ErrorDispatcherValve.java:171)
	at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:172)
	at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641)
	at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
	at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:174)
	at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)
	at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
	at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
	at org.apache.coyote.tomcat4.CoyoteAdapter.service(CoyoteAdapter.java:223)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:601)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:392)
	at org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:565)
	at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:619)
	at java.lang.Thread.run(Thread.java:534)


root cause 

java.lang.IllegalArgumentException: argument type mismatch
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:324)
	at org.apache.commons.beanutils.PropertyUtils.setSimpleProperty(PropertyUtils.java:1789)
	at org.apache.commons.beanutils.PropertyUtils.setNestedProperty(PropertyUtils.java:1684)
	at org.apache.commons.beanutils.PropertyUtils.setProperty(PropertyUtils.java:1713)
	at org.apache.commons.beanutils.BeanUtils.setProperty(BeanUtils.java:1019)
	at org.apache.commons.beanutils.BeanUtils.populate(BeanUtils.java:808)
	at org.apache.struts.util.RequestUtils.populate(RequestUtils.java:1252)
	at org.apache.struts.action.RequestProcessor.processPopulate(RequestProcessor.java:821)
	at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:254)
	at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1482)
	at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:525)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:760)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:247)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:256)
	at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)
	at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
	at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
	at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)
	at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
	at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
	at org.apache.catalina.core.StandardContext.invoke(StandardContext.java:2416)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:180)
	at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)
	at org.apache.catalina.valves.ErrorDispatcherValve.invoke(ErrorDispatcherValve.java:171)
	at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:172)
	at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641)
	at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
	at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:174)
	at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)
	at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
	at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
	at org.apache.coyote.tomcat4.CoyoteAdapter.service(CoyoteAdapter.java:223)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:601)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:392)
	at org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:565)
	at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:619)
	at java.lang.Thread.run(Thread.java:534)



--------------------------------------------------------------------------------

Apache Tomcat/4.1.27



型があっていないと言う旨のメッセージだと思います。

ファイル数が決まっていれば、
コード:
JSP:
<html:file property="theFile[0]"・・・
<html:file property="theFile[1]"・・・

ActionForm:
private FormFile[] theFile = new File[2];


のようにしてファイルを取得できることは分かったのですが、これでは動的に変化する
ファイル数に対応できません。

何かわかる方はアドバイスをお願い致します。

開発環境:
jdk1.4.2_01
Tomcat 4.1.27
Struts 1.1
ブラウザ IE6 SP1
かずくん
ぬし
会議室デビュー日: 2003/01/08
投稿数: 759
お住まい・勤務地: 太陽系第三惑星
投稿日時: 2003-12-24 18:01
ほかにもっと言い方法はあると思いますが、後ろ向きな解決法として、
クライアント側であらかじめ複数のファイルを圧縮しておき、その圧縮ファイルをアップロード。
サーバー側では、圧縮ファイルを展開という方法じゃだめかな?

追加:
ちなみにアイデア元は、以下のサイトのきじゅつです。
http://java.ittoolbox.com/pub/SC071902/httprevealer_servlets_itx.htm
この逆パターンだとどうかなって思いました。

[ メッセージ編集済み 編集者: かずくん 編集日時 2003-12-24 18:07 ]
masaka
常連さん
会議室デビュー日: 2003/08/04
投稿数: 27
お住まい・勤務地: 東京
投稿日時: 2003-12-24 18:03
ActionForm内でFormFileインスタンスを配列として保持していますが、これをListやMapにすればよいのではないでしょうか?

もちろんgetter,setterもそれにあわせて修正する必要があります。
masaka
常連さん
会議室デビュー日: 2003/08/04
投稿数: 27
お住まい・勤務地: 東京
投稿日時: 2003-12-24 18:21
簡単にサンプルを書くとこんな感じです。動作は確認していないので、正しく動くか保証できませんが…
コード:
private Map fileMap = new HashMap();

public FormFile getFile( int index )
{
  return (FormFile) fileMap.get( new Integer( index ) );
}

public FormFile setFile( int index, FormFile file )
{
  fileMap.put( new Integer( index ), file );
}

public FormFile getFiles()
{
  return (FormFile[]) fileMap.values().toArray( new FormFile[fileMap.size()] );
}



JSPの方はこんな感じでいいと思います。fileタグは必要に応じてiterateタグなどを利用して動的に増やせばいいのではないでしょうか?
コード:
<html:file property="file[0]"・・・
<html:file property="file[1]"・・・

ちば
大ベテラン
会議室デビュー日: 2003/02/14
投稿数: 114
お住まい・勤務地: 都内勤務
投稿日時: 2003-12-24 18:35
かずくんさん、masakaさん、早速のお返事有難うございます。

>かずくんさん
引用:

ほかにもっと言い方法はあると思いますが、後ろ向きな解決法として、
クライアント側であらかじめ複数のファイルを圧縮しておき、その圧縮ファイルをアップロード。
サーバー側では、圧縮ファイルを展開という方法じゃだめかな?


なるほどと思いましたが、今回の仕様上無理でした

>masakaさん
引用:

簡単にサンプルを書くとこんな感じです。動作は確認していないので、正しく動くか保証できませんが…
コード:
--------------------------------------------------------------------------------
 
private Map fileMap = new HashMap();

public FormFile getFile( int index )
{
  return (FormFile) fileMap.get( new Integer( index ) );
}

public FormFile setFile( int index, FormFile file )
{
  fileMap.put( new Integer( index ), file );
}

public FormFile getFiles()
{
  return (FormFile[]) fileMap.values().toArray( new FormFile[fileMap.size()] );
}


--------------------------------------------------------------------------------




JSPの方はこんな感じでいいと思います。fileタグは必要に応じてiterateタグなどを利用して動的に増やせばいいのではないでしょうか?
コード:
--------------------------------------------------------------------------------

<html:file property="file[0]"・・・
<html:file property="file[1]"・・・



これで出来ました!

ずっとJSPで指定しているproperty名とActionFormクラスのメンバを同じ名前にして、
型も同じになるようにして・・・と考え方が堅かったです。
ちなみにJSPでの表示ですが、その前にActionクラスを通して生成するため、個数に関しては
あまり気にしないでよいことになっています。

有難うございました。
1

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