- ベストアンサー
RFC1867 Form Based File Upload での 転送可能サイズ
FormBasedFileUploadでは、転送サイズに制限があるのでしょうか? 9MByteを超えるファイルの転送に失敗してしまいます。 javax.servlet.ServletException: java.lang.OutOfMemoryError になります。 コーディングに問題があるのでしょうか、、というか、コーディングしだいで解決できるものでしょうか? または、サーブレットコンテナ側で調整するものでしょうか? どなたか、ご教授くださるよう、お願いいたします。 ※サーブレットコンテナは、TomCat4.1です。 原田洋子さんの「ファイルをアップロードしてみんとす」とか、Nemunekoさんの「Httpでサーバにファイルを転送する」を熟読して、複数のFormタグの複数の属性をファイルと一緒に転送できるように、Nemunekoさんの、MulitipartBeanを参考に、ようやくファイル部のバウンダリを抽出できるようになったのですが、、、、
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
- ベストアンサー
> ヒープサイズって何のことでしょう? ヒープサイズとは、JavaVMが利用可能な物理メモリサイズのことです。 > また、-Xmx200mは、どういうオプションで、通常何も指定しなかった > 場合、デフォルト値は、どうなっているのでしょうか? -XmxNNm で、JavaVMは「最大 NN MByteまで利用してよい」ということを表します。 なお、JDK1.4ではデフォルトが64MByteです。 > やはり、コーディングが悪いのですね。。。 そういうことになります。 > ところで、何故、こんなことをしているのかと言うと、、 > WEBクライアントから、ファイルと、その他の情報を同時に送信したい > からです。input type=text と、input type=fileから、保管される > ファイル名は、きちんと管理されたファイル名にしたいわけなのです。 ↑を実現するにしても、メモリ上に全てを保存する必要はありません。 例えば、アップロードされたファイルについては、テンポラリの ファイルに一度保存しておいて、プログラム上にはそのテンポラリ ファイルへのパスのみをメモリに格納します。で、最後にテンポラリファイルを クライアントの情報に基づいたファイル名に変名するかコピーすれば すみます。。。
その他の回答 (2)
yuji さんが記述されている方法で回避できると思いますが、 9MByteのファイルをアップロードしただけで、OutOfMemory を起こすということですから、プログラム的に問題があるかも しれません。。。 サーブレットの場合、複数のクライアントから同時にアクセス されることを考える必要がありますから、1クライアントが ファイルをアップロードすることでOutOfMemoryを起こしてしまう ようですから、ヒープサイズを大きくしただけでは、そのうち問題を 起こすようになるかもしれません。 アップロードされたファイルをそのままテンポラリの領域に 格納してからファイルに出力するような無理なプログラムを 作っていませんか?
補足
WEBクライアントから、受けたストリーミングを確認する為に、DataInputStreamをByteArrayOutputStreamに取り込ませ、byte配列(変数名:buffer)に保管しています。 このbufferから、WEBの<FORM>タグ<input Type=file・・・>の属性に相当する、内容を最初から何バイト目のバウンダリにあるかをチェックし、ファイルを取り出しています。 そこで、きちんと機能するまで、確認用に、全てのbufferをStringに変換し、WEBに表示させていました。この機能を削除すると、9Mbyteの壁は、消えたのです。 が、、今度は、15Mbyteで駄目でした。 やはり、コーディングが悪いのですね。。。 #ところで、何故、こんなことをしているのかと言うと、、 WEBクライアントから、ファイルと、その他の情報を同時に送信したいからです。input type=text と、input type=fileから、保管されるファイル名は、きちんと管理されたファイル名にしたいわけなのです。
- yuji
- ベストアンサー率37% (64/169)
Tomcatを起動するときの JVM のオプションとして、 -Xmx200m みたいにヒープサイズを大きくしてみてはどうでしょうか?
補足
不勉強で、申し訳ありませんが、ヒープサイズって何のことでしょう? また、-Xmx200mは、どういうオプションで、通常何も指定しなかった場合、デフォルト値は、どうなっているのでしょうか? よろしくお願いいたします。
補足
ありがとうございました。JAVAと言えども、最低限のメモリ管理・微調整が必要なのですね。 さて、仰るとおり、コーディングを見直し、以前は、最初にrequestからのDataInputStream から作成していた変数disを先のByteArrayOutputStream baoへ渡していたのを止めて、直接baoへ渡すことと、ByteArrayOutputStream baoで、作成したByte[]の配列変数bufferから、file部分を切り出した、byte[]dataを作って、FileOutputStream foへ渡していたのも、foへ直接dataに相当するbufferのオフセットを指定することで、デフォルトで、30Mbyte転送できるようになりました。 ただどうしても、file作成時、WEBクライアントから送られる、内容には、余計なバウンダリが存在する為に、やはり、一旦、解析用に全てを取り込むバッファが必要になりますが。。。