home ホーム search 検索 -  login ログイン  | reload edit datainfo version cmd icon diff delete  | help ヘルプ

Groovy/GroovyServlet でファイルアップロード (multipart-formdata)

Groovy/GroovyServlet でファイルアップロード (multipart-formdata)

Groovy / GroovyServlet でファイルアップロード (multipart-formdata)
id: 1187 所有者: msakamoto-sf    作成日: 2013-04-13 22:09:12
カテゴリ: Groovy 

GroovyServletでファイルアップロードを処理させようとしたところ、思いっきり落とし穴に嵌りましたのでメモ。

時間がない方向けの結論:

  1. GroovyServletでは、内部でHttpServletRequestのパラメータを読みだして独自にBindingしている。
    1. → このため、HttpServletRequest.getInputStream()を(恐らくContainer側の実装にも依ると思うが)GroovyServletの内部処理で読みきってしまう。
    2. → GroovyServlet上で動作するスクリプトからは、(既に読みきってしまっているため)HttpServletRequest.getInputStream()からHTTPリクエストのBODYデータを読み込めない。
    3. (もしかしたらInputStream.reset()を呼べば良いかもしれないが、関連トピックで調べてみたところあまりreset()を使う解法が無かったっぽいので、駄目なのかもしれない。)
  2. 解法:Servletを呼ぶ前に独自のFilterでgetInputStream()からbyte[]型に読み出し、それをHttpServletRequestWrapper派生の独自ラッパーで包み込んだのを本体Servletに渡す。
    1. これにより、独自ラッパー内のbyte[]型として何回でもByteArrayInputStream経由で読み出せるようになる。
    2. 多分GroovyServletとの副作用も無いっぽい。
    3. Apache Commons FileUpload も使えたので、多分これで行けるだろう。実際好きなタイミングでリクエストボディ取り出せるのは便利。
    4. この時用意するFilterとかラッパーについては以下の詳細説明を参照してください。

用意するFilterやラッパーについては、以下のBlogが詳しいです。

GroovyServletのサンプルにも組み込んでいます。


以下、落とし穴に嵌ったのを認識する前段階からの足跡。

1.Apache Commons FileUploadを使おうと、練習にまずはHttpServletRequest.getInputStream()を使ってみる。

・・・が、getInputStream()しても正常に取れない・・・。

2.自分が嵌るくらいだから、既に誰か対処法見つけてるんじゃないの?

・・・できてるようではあるが・・・記事も古く、バージョンも大分古いので内部動作も変わってしまってるのかも。

3.ようやく、ServletAPIを確認しようとひっくり返してみる。

これでようやく、getParameter系とかgetReader/getInputStreamって併用すると副作用ある感じ?ということに気づく。

4.getParameter系呼んだ後にgetInputStream()呼び出してトラブった人いないかな?

どうもPOSTの場合にgetParameter系呼ぶと、リクエストボディのストリーム(?)を読みきってしまい、その後にgetInputStream()を読んでも、既に読みきってしまってるため手遅れ状態っぽい・・・。

→最終的にGroovyServletの中身(=Groovyのソースコード)をたどったところ、GroovyServletのBinding中でgetParamXXXX()してるためか、その影響でgetInputStream()に副作用が生じているものと思われます。



プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2013-04-13 22:11:14
md5:a9098fa9bed933430900c83a1ea07a73
sha1:e51ff238d041118df5fb98bf641f0218c0e1b05d
コメント
コメントを投稿するにはログインして下さい。