ajax通信で少しハマった
ajax通信を使ってデータをバックエンドに送信する際、少し仕様でハマった話です。
はじめに
jQueryの$.ajaxを使ってFormDataオブジェクトを送信する際に、クエリパラメータが正しく送信されない問題に遭遇したので、その原因と解決方法をまとめました。
やりたかったこと
jQueryの$.ajaxを使って、クエリパラメータとFormDataを同時にサーバーへ送信したい、という状況でした。
具体的には、以下のようなコードを書いていました。
const formData = new FormData();
formData.append('file', fileInput.files[0]);
$.ajax({
url: '/submit?userId=123',
method: 'POST',
dataType: 'json',
data: formData,
processData: false,
contentType: false
});
発生した問題
上記のコードで、processData: falseとcontentType: falseを指定しているにもかかわらず、URLに指定したクエリパラメータuserIdがサーバー側で受け取れませんでした。
原因
調査したところ、jQueryの$.ajaxはdataプロパティにFormDataオブジェクトを指定した場合、URLに含まれるクエリパラメータを自動的に処理しない仕様になっているようです。
つまり、dataにFormDataを指定すると、URLのクエリパラメータが無視されてしまうという挙動になります。
解決方法
クエリパラメータとして送信したかったデータを、FormDataオブジェクトに直接追加することで解決できました。
const formData = new FormData();
formData.append('userId', '123'); // クエリパラメータではなくFormDataに追加
formData.append('file', fileInput.files[0]);
$.ajax({
url: '/submit', // クエリパラメータを削除
method: 'POST',
dataType: 'json',
data: formData,
processData: false,
contentType: false
});
この方法により、userIdもファイルデータも正しくサーバーに送信されるようになりました。
補足: processDataとcontentTypeについて
-
processData: false - jQueryがデータを自動的にクエリ文字列に変換するのを防ぎます。
FormDataを使う場合は必須の設定です。 -
contentType: false - jQueryが自動的に
Content-Typeヘッダーを設定するのを防ぎます。FormData使用時はブラウザが適切なContent-Type(multipart/form-dataとboundary)を自動設定するため、falseにする必要があります。
まとめ
- jQueryの
$.ajaxでFormDataを使用する際、URLのクエリパラメータは無視される - クエリパラメータとして送りたいデータは、
FormDataに直接追加することで解決できる -
processData: falseとcontentType: falseの設定はFormData送信時に必須
(余談)私はサッカーが好きなのでajaxを見ると「アヤックス」と読みがちです。
同じような問題に遭遇した方の参考になれば幸いです。