POSTってなに?
POST メソッドというのは、HTTP リクエストでデータを送受信する方法の一つです。
送受信するデータはアドレスバーなどには表示されず、画像などのバイナリデータも扱うことができます。
データを見られたくない場合や大容量のデータ、バイナリデータなどを扱うのに適しています。
アドレスバーにデータが表示される GET メソッドも良く使われ、アドレスの "?" 以降に "データ名=データ値(&データ名=データ値…)" というように簡単にデータを見ることができる方式です。
最近のブラウザでは "?" 以降を自動的に表示しないようになっていることが多いので、目にしないことも増えています。
(但し、アドレスバーを選択すれば GET データは見ることができます)
ここから分かる通り、GET でのデータはアドレスの "?" 以降につけることで簡単に扱うことができ、気軽に使うことができます。
一方 POST は、データを送受信する仕組みを組む必要があります。
ちなみに、HTML の <FORM> 要素を使えば、簡単に POST 送信をことができます 。が、データ送信にはページ遷移を伴います。
Google 検索では見られても困ることはないので GET で検索語などの情報を扱っています。
もう少し詳しくまとめた記事が Qiita さんのサイトにあるので、興味のある方はこちらもご確認下さい。
・Qiita - HTTPとPOSTとGET
XHR通信をする方法
XHRとは?
XHR とは XMLHttpRequest の略で、サーバとブラウザ間でのデータのやり取りを非同期、つまりページが読み込まれた後の任意のタイミングでデータのリクエストを行えるというものです。
これによりページの遷移無しに新たなデータをサーバから読み込んだりできます。便利ですね。
最初からページ内の要素を全て読み込んでも良いのですが、一度に大量のデータを読み込むと時間が掛かる上にスクロールされなかった (表示されない) 要素のリソースはムダになってしまうので、XHR などを用いて非同期で少しずつ読み込む方が良いです。
早く表示されるページはユーザにも Google にも好まれますのでアクセスUPにも繋がります。
軽量なサイトやページを構築したい方には必須の技術です。
XHRの基本の使い方
XHR による通信には専用のオブジェクト (XHR の通信を行うための手段が色々格納されているもの) が用意されています。
そのため、以下のように簡単に実行することが可能です。
// new演算子でXHRオブジェクトの実体を生成します
// 変数名は任意に指定できます
var XHR = new XMLHttpRequest();
// .open()メソッドで"どんな方式"で"どんなアドレス"に"非同期にするか"をしていします
// 第3引数に"false"を渡すと同期通信となり、.send()以降はレスポンスが返ってくるまで実行されません
// ("true"で非同期通信にすればレスポンスが返ってこなくても.send()以降が実行されます)
XHR.open("POST", "./hoge/fuga.php", true);
// 変数postDataに格納されたデータを送信します
// GETなどで不要な場合は"null"を入れます
// XHR.send(null);
XHR.send(postData);
たったこれだけで XHR による通信が実現できます。
ページのソースファイルを取得してみる
では、実際に XHR でのデータ取得を見てみましょう。
まずは簡単にこのサイトの TOP ページのソースファイルを取得します。
ソースファイルを取得するには、GET でサーバにリクエストを投げればレスポンスとしてソースファイルが取得できます。
但し、HTTP サーバのレスポンスになるので PHP などのサーバ側での処理は完了して結果の HTML となります。
(PHP 等の実行ファイルを取得したい場合は、中身を文字列として返すような PHP を作成してそこにリクエストすれば取得できます)
<Javascript>
var getSourceFile = function($URL){
// XHRの宣言
var XHR = new XMLHttpRequest();
// TOPページ($URL = https://web.analogstd.com/)にGETでリクエストする
XHR.open("GET", $URL, true);
// ブラウザからサーバへ送る情報は不要なのでnullを指定する;
XHR.send(null);
// サーバの応答をonreadystatechangeイベントで検出して正常終了したらデータを取得する
XHR.onreadystatechange = function(){
if(XHR.readyState == 4 && XHR.status == 200){
document.getElementById("source_topPage").value = XHR.responseText;
}
};
}
// ページ読込完了後にボタンにclickイベントを登録する
window.addEventListener("load", function(){
document.getElementById("getSourceRun").addEventListener("click", function(){
// クリックしたらソースを取得しに行く
getSourceFile("https://web.analogstd.com/");
}, false);
}, false);
<HTML>
<button type="button" id="getSourceRun">ソースファイル取得</button>
<textarea id="source_topPage" style="width:95%;height:400px;" placeholder="ここにソースが表示されます"></textarea>
このようにして簡単にソースファイルの取得ができました。
XHR の状態を表す "XHR.readyState" が "4" に変わったタイミングで処理が完了したことを表します。レスポンスの取得に成功したかはここでは分かりません。
readyState の値がそれぞれなにを表すかは、以下ページをご確認下さい。
・MDN Web Docs - XMLHttpRequest.readyState
同様に "XHR.status" はHTTPのリクエストに対するレスポンスを返します。
この値が "200" で正常な応答ができたことを表します。良く目にするのは500番台のサーバエラーです。
こちらも詳しくは以下をご確認下さい。
・MDN Web Docs - XMLHttpRequest.status
・MDN Web Docs - HTTP レスポンス状態コード
XHRを使ってPOSTでデータを送信する方法
ようやく本題です。
XHR を使って POST でデータを送信してみましょう。
HTML の <FORM> 要素を使う方法と使わない方法の2つについて解説します。
やはりフォームを使う方が簡単にデータを送信することができます。
HTMLフォームのデータを使う場合
フォームに入力されているデータを使う場合は、以下のようにして簡単にデータをセットすることができます。
FormData オブジェクトを使うことで簡単なコードで実現することができます。
<Javascript>
// ページ読込完了後にボタンにclickイベントを登録する
window.addEventListener("load", function(){
document.getElementById("send_userinfo").addEventListener("click", function(){
// FoemDataオブジェクトを実体化する際にHTMLフォームのセレクタを渡せば
// データのキーと値をセットで準備することができます
var formDatas = document.getElementById("userinfo");
var postDatas = new FormData(formDatas);
// XHRの宣言
var XHR = new XMLHttpRequest();
// openメソッドにPOSTを指定して送信先のURLを指定します
XHR.open("POST", "./hoge/fuga.php", true);
// sendメソッドにデータを渡して送信を実行する
XHR.send(postDatas);
// サーバの応答をonreadystatechangeイベントで検出して正常終了したらデータを取得する
XHR.onreadystatechange = function(){
if(XHR.readyState == 4 && XHR.status == 200){
// POST送信した結果を表示する
document.getElementById("userinfo_response").innerHTML = XHR.responseText;
}
};
} ,false);
}, false);
<HTML>
<form id="userinfo">
<p>
<label for="item1">名前</label>
<input name="name" id="item1">
</p>
<p>
<label for="item2">年齢</label>
<input name="old" id="item2">
</p>
<p>
<label for="item3">住所</label>
<input name="address" id="item3">
</p>
</form>
<p>
<button type="button" id="send_userinfo">送信</button>
</p>
<div id="userinfo_response">
<!-- 結果を出力する -->
</div>
POST によるデータ送信なので <input type="file"> のようなファイル選択要素を利用すればローカルファイルの送信にも対応します。
これにより画面遷移しない画像のアップローダを作成することなどに応用できます。
HTMLフォームを使わない場合
フォームを使わない場合でも FormData オブジェクトを使うことで POST 送信ができます。
<Javascript>
// ページ読込完了後にボタンにclickイベントを登録する
window.addEventListener("load", function(){
document.getElementById("send_fixdata").addEventListener("click", function(){
// FoemDataオブジェクトに要素セレクタ(引数)を渡さずに宣言する
var fixedDatas = new FormData();
// appendメソッドでキーとデータの組をセットする
// append("キー(FORMで云うところのname属性値)", "データ")でデータをセットできる
fixedDatas.append("filename", "test.txt");
fixedDatas.append("filesize", "10,154B");
// XHRの宣言
var XHR = new XMLHttpRequest();
// openメソッドにPOSTを指定して送信先のURLを指定します
XHR.open("POST", "./hoge/fuga.php", true);
// sendメソッドにデータを渡して送信を実行する
XHR.send(fixedDatas);
// サーバの応答をonreadystatechangeイベントで検出して正常終了したらデータを取得する
XHR.onreadystatechange = function(){
if(XHR.readyState == 4 && XHR.status == 200){
// POST送信した結果を表示する
document.getElementById("fixdata_response").innerHTML = XHR.responseText;
}
};
} ,false);
}, false);
<HTML>
<p>
<button type="button" id="send_fixdata">固定データを送信する</button>
</p>
<div id="fixdata_response">
<!-- 結果を出力する -->
</div>
HTMLフォームのデータにJavascriptでデータを追加して送信する場合
上記を組み合わせて使用することもできます。
<input type="hidden"> 要素を使用しなくても送信するデータを増やすことができます。
<Javascript>
// ページ読込完了後にボタンにclickイベントを登録する
window.addEventListener("load", function(){
document.getElementById("send_mixdata").addEventListener("click", function(){
// FoemDataオブジェクトに要素セレクタを渡して宣言する
var formDatas = document.getElementById("userinfo2");
var mixedDatas = new FormData(formDatas);
// appendメソッドでキーとデータの組をセットする
// append("キー(FORMで云うところのname属性値)", "データ")でデータをセットできる
// appendではデータは追加となる
mixedDatas.append("filename", "test.txt");
mixedDatas.append("filesize", "10,154B");
// XHRの宣言
var XHR = new XMLHttpRequest();
// openメソッドにPOSTを指定して送信先のURLを指定します
XHR.open("POST", "./hoge/fuga.php", true);
// sendメソッドにデータを渡して送信を実行する
XHR.send(mixedDatas);
// サーバの応答をonreadystatechangeイベントで検出して正常終了したらデータを取得する
XHR.onreadystatechange = function(){
if(XHR.readyState == 4 && XHR.status == 200){
// POST送信した結果を表示する
document.getElementById("mixdata_response").innerHTML = XHR.responseText;
}
};
} ,false);
}, false);
<HTML>
<form id="userinfo2">
<p>
<label for="item1">名前</label>
<input name="name" id="item1">
</p>
<p>
<label for="item2">年齢</label>
<input name="old" id="item2">
</p>
<p>
<label for="item3">住所</label>
<input name="address" id="item3">
</p>
</form>
<p>
<button type="button" id="send_mixdata">入力値と固定値を送信する</button>
</p>
<div id="mixdata_response">
<!-- 結果を出力する -->
</div>
まとめ
以上、XHR を利用したページ遷移を伴わない POST データ送信についてまとめました。
ページ遷移させたくないけど POST したいといった場合に参考にしてみて下さい。