はじめに
- ajaxを使用してファイルをpostで送るときに詰まったので備忘録として残しておきます。
.serialize()が使えない
- .serialize() や.serializeArray()を使用すると性質上勝手にform内のinput type=file属性の要素が除外されてしまうようです。
なので上記2つの方法を使用した正攻法でのファイル転送は行えません。
※それでも無理やり送ろうとする場合は別でfile属性の要素を取得してbase64などの方式でエンコードを行い、上記のデータの後ろにJSONなどでくっつけてcontroller側でデコードを行えば、やってできないことはないかもしれないです(未確認)。
ajaxで情報をpost送信する
index.html
<form id="account_form" enctype="multipart/form-data" method="post">
<div class="email-area">
<span>メールアドレス:</span>
<input type="text" id="email" name="email"/>
</div>
<div class="nick-name-area">
<span>ニックネーム:</span>
<input type="text" id="nick_name" name="nick_name"/>
</div>
<div class="file-area">
<span>添付ファイル:</span>
<input type="file" id="file_data" name="file_data" />
</div>
<div class="submit-area">
<input type="button" id="submit_btn" value="送信" onclick="post_with_ajax()"/>
</div>
</form>
例えばこんな入力フォームがあったとします。
index.js
function post_with_ajax() {
let formData = $('#account_form');
$.ajax({
type: "post",
url: "/accountForm",
data: formData.serialize(),
}).done(function(resData) {
//成功時の処理
}).fail(function(resData) {
//エラー時の処理
});
}
.serialize()が使用できれば上記の記述で/accountFormにデータが送れます。
ところが.serialize()は無言でファイルデータを送信対象から外してしまうため、今回のフォームに使用すると添付ファイルデータは送信対象外となってしまいます。
なので、下記のように書き換えます。
index.js
$("#submit_btn").click(function () {
//formセレクタを取得
let form = $('#account_form').get(0);
//FormData オブジェクトを作成
let formData = new FormData( form );
//ajax実行
$.ajax({
url : "/accountForm",
dataType: "html",
type : "post",
data : formData, // dataに FormDataを指定
processData: false, //ajaxがdataを整形しない指定
contentType: false //contentTypeもfalseに指定
}).done(function(resData) {
//成功時の処理
}).fail(function(resData) {
//エラー時の処理
});
});
こう書き換えることで、ajaxを通さずsubmitでフォーム送信した時と同じデータが、/account_formに送られるようになります。
参考文献