Javaでファイルアップロード用のcommonライブラリFileUploadを利用しているアップローダーが、IE10/11でだけうまく動かない、という問題が発生しました。
JavaScriptのFormDataオブジェクトを使ってjQueryのajaxでデータを送信しているのですが、IEからだと受け取ったサーバ側でエラーがでていました。
エラーの応答とtomcatのログを確認すると、下記のエラーが記録されていました。
原因 javax.servlet.ServletException: org.apache.commons.fileupload.FileUploadException: Stream ended unexpectedly
どうもIEから送られるmultipart/form-dataではFileUpload側でデータ終了の検知がうまくいかないため、エラーになっているようでした。
そこでこのエラーメッセージから情報を探してみると、同様の現象がFlushクライアントからでも発生しており、そのパッチがあたっていることがわかりました。
http://commons.apache.org/proper/commons-fileupload/changes-report.html
"Stream ended unexpectedly" when posting from a Flash client Fixes FILEUPLOAD-143. Thanks to Luke Scott.
利用していた環境では1.2が利用されており、この修正は1.3で当たっているため、FileUploadを最新の1.3.1にアップデートして試してみたところ、IE11でも問題なく動くことが確認できました。
というわけで、IE10/11だけでのみFileUploadとFormData使ったアップロードがうまくいかない場合、FileUploadのバージョンが1.3より古い場合は「commons-fileupload-1.3.1.jar」など1.3以上にバージョンアップすることをおすすめします。
…と書いたのですが、うまく行ったように思ってたのが勘違いでした…
1.3.1に変更しても改善していませんでした。うああ orz
このエントリーを書こうとしてFormDataでググっていた時に出てきたエントリーがあり、これと同じ問題のようでした。
JavaScript - ハマりメモ:IE10でFormData Objectを使った$.ajax()が失敗 - Qiita
http://qiita.com/marsa746079/items/a3c69465d605a0078a6b
ここで紹介されている、この問題を解析したエントリーによると
Ajax with FormData is Broken on IE10 / IE11 in Some Conditions
http://blog.yorkxin.org/posts/2014/02/06/ajax-with-formdata-is-broken-on-ie10-ie11
- radioやcheckboxのような入力欄がフォームの最後にある
- それらの入力欄にチェックが入っていない
- FormDataオブジェクトをajaxで送信している
- IE10/11で送信する
という条件だと送信データのフォーマットに下記のような壊れたゴミデータがついてしまうそうです。
-----------------------------7de3af25e0204 Content-Disposition: form-data; name=" -----------------------------7de3af25e0204--
ということで、フォームの最後に
<input type="hidden" name="_dummy">
というダミーの入力欄をいれてやることで解決出来ました。
なんというバッドノウハウ。はあ…