47
46

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ハマりメモ:IE10でFormData Objectを使った$.ajax()が失敗

Posted at

##ハマった事象
IE10でJQuery.ajax()のdataパラメータにformDataオブジェクトを渡したら、
リクエスト内容が壊れてしまった。
具体的には以下のようなコードを書いた(細部は変えてある)

hoge.html
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>ほげほげ</title>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script>
      function onSubmit() {
          var form = $('#hogeForm').get(0);
          var formData = new FormData(form);
          
          $.ajax({
            url: '/hogeAction',
            type: 'POST',
            contentType: false,
            processData: false,
            data: formData,
            dataType: 'json',
          });
          return false;
      }
    </script>
  </head>
  <body>
    <form name="hogeForm" id="hogeForm" method="post" action="/hogeAction" enctype="multipart/form-data">

    <select id="selection" name="selection">
      <option value="1">選択1</option>
      <option value="2">選択2</option>
      <option value="3">選択3</option>
    </select>
    <div>区分
      <input type="radio" name="kubun" value="1" checked="checked"><input type="radio" name="teikyouKbn" value="0"></div>
    <div>タイプ選択1
      <input type="radio" name="type" value="1" checked="checked" id="fileType1">タイプ1
      <input type="radio" name="type" value="2" id="fileType2">タイプ2
    </div>
    <input type="file" name="file" size="70" value="" style="font-size:9pt;">
    <div>タイプ選択2
      <input type="radio" name="type2" value="1" checked="checked" id="fileType1">タイプ1
      <input type="radio" name="type2" value="2" id="fileType2">タイプ2
    </div>
    <input type="button" id="submitButton" onClick="onSubmit()" name="submitButton" value="submit" />
    </form>
  </body>
</html>

submitボタンを押すと、onSubmit()メソッド内でnew FormData(form)して、
作成されたFormDataオブジェクトを$.ajax()でPOSTする。
これを動かすと、以下のように、リクエストの最後に謎のContent-Dispositionヘッダが付与されてしまい、
POST受信側でリクエストをパースできない状況になった。

Request
POST http://xxxxxxxxxx/hogeAction HTTP/1.1
X-Requested-With: XMLHttpRequest
Accept: application/json, text/javascript, */*; q=0.01
Content-Type: multipart/form-data; boundary=---------------------------7de1df1690910
Referer: http://xxxxxxxxxx/
Accept-Language: ja-JP
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)
Host: xxxxxxxxxxx
Content-Length: 659
DNT: 1
Connection: Keep-Alive
Pragma: no-cache
Cookie: xxxxxxxxx

-----------------------------7de1df1690910
Content-Disposition: form-data; name="selection"

1
-----------------------------7de1df1690910
Content-Disposition: form-data; name="kubun"

1
-----------------------------7de1df1690910
Content-Disposition: form-data; name="type"

1
-----------------------------7de1df1690910
Content-Disposition: form-data; name="file"; filename=""
Content-Type: application/octet-stream


-----------------------------7de1df1690910
Content-Disposition: form-data; name="type2"

1
-----------------------------7de1df1690910
Content-Disposition: form-data; name="
-----------------------------7de1df1690910--

##回避策
頑張ってググったところ、ずばりこの問題を扱っているサイトを見つけた。
http://blog.yorkxin.org/posts/2014/02/06/ajax-with-formdata-is-broken-on-ie10-ie11
上記サイトの検証によると、Formの最後にあるinput要素(button/submitを除く)が「チェックされていないラジオボタンorチェックボックス」の場合、この現象が起きるようだ。
上記サイトの例に倣って、ダミーのinput hiddenを追加する。

hoge.html
  ...
  <body>
    <form name="hogeForm" id="hogeForm" method="post" action="/hogeAction" enctype="multipart/form-data">

    <select id="selection" name="selection">
      <option value="1">選択1</option>
      <option value="2">選択2</option>
      <option value="3">選択3</option>
    </select>
    <div>区分
      <input type="radio" name="kubun" value="1" checked="checked"><input type="radio" name="teikyouKbn" value="0"></div>
    <div>タイプ選択1
      <input type="radio" name="type" value="1" checked="checked" id="fileType1">タイプ1
      <input type="radio" name="type" value="2" id="fileType2">タイプ2
    </div>
    <input type="file" name="file" size="70" value="" style="font-size:9pt;">
    <div>タイプ選択2
      <input type="radio" name="type2" value="1" checked="checked" id="fileType1">タイプ1
      <input type="radio" name="type2" value="2" id="fileType2">タイプ2
    </div>
    <input type="hidden" name="dummy" value="dummy">
    <input type="button" id="submitButton" onClick="onSubmit()" name="submitButton" value="submit" />
    </form>
  </body>
</html>

再度リクエスト内容を確認する。

Request
POST http://xxxxxxxxxx/hogeAction HTTP/1.1
X-Requested-With: XMLHttpRequest
Accept: application/json, text/javascript, */*; q=0.01
Content-Type: multipart/form-data; boundary=---------------------------7de37a3190910
Referer: http://xxxxxxxxxx/
Accept-Language: ja-JP
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)
Host: xxxxxxxxxxx
Content-Length: 674
DNT: 1
Connection: Keep-Alive
Pragma: no-cache
Cookie: xxxxxxxxx

-----------------------------7de37a3190910
Content-Disposition: form-data; name="selection"

1
-----------------------------7de37a3190910
Content-Disposition: form-data; name="kubun"

1
-----------------------------7de37a3190910
Content-Disposition: form-data; name="type"

1
-----------------------------7de37a3190910
Content-Disposition: form-data; name="file"; filename=""
Content-Type: application/octet-stream


-----------------------------7de37a3190910
Content-Disposition: form-data; name="type2"

1
-----------------------------7de37a3190910
Content-Disposition: form-data; name="dummy"

dummy
-----------------------------7de37a3190910--

正しいリクエストになったようだ。やれやれ。

47
46
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
47
46

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?