chapter3. 送信
今回は XMLHttpRequest を使ったデータの送信について説明したいと思います。

XMLHttpRequest では、データ送信のメソッド(簡単に言うと種類)として、
GET, POST, PUT, PROPFIND が使用できます。
メソッドが異なることで送信出来るデータや、
送信されたデータをサーバで受け取る際に違いが出てきます。
それぞれの違いを Google で調べたので、簡単に説明します。

GET 最も一般的に使用されるメソッドです。
ブラウザはサーバに対してページの取得を要求します。
POST CGI でよく使用されるメソッドです。
method="POST" を指定したフォームに入力したデータをサーバに転送する際に使用されます。
PUT ファイルをサーバにアップロードする際に用いられます。
PROPFIND プロパティの検索に用いる(らしいです)。よくわかりません。

ここでは、使用頻度の高い GET, POST を用いて紹介します。

メソッドは、XMLHttp でのページの取得命令である open で指定します。(詳細 : open
 open の使用例 
xmlhttp.open('GET', './sample1.php');

GET でのデータ送信には、open の URL 欄を使用します。
 open の使用例 
xmlhttp.open('GET', './sample1.php?name=nanashi&body=test');

POST でのデータの送信には、XMLHttp での送信命令である send を使用します。(詳細 : send
 send の使用例 
xmlhttp.send('name=nanashi&body=test');

以上で、後は、サーバ側で、送信データのメソッドに対応したデータ取得方法を用いて
処理すれば OK です。

・・・と言いたいところですが、このまま送信しても残念ながらデータを受け取ることが出来ません。
送信データのタイプを変更する必要があります。
これは、setRequestHeader を設定すれば良いのですが、以下のように非常に簡単です。
 setRequestHeader の使用例 
xmlhttp.setRequestHeader("Content-Type" , "application/x-www-form-urlencoded");

おまけに、データのエンコード(いわゆる暗号化処理)を自動でしてくれます。
 memo 
IE / Firefox で比較したところ、GET, POST でおかしな挙動があります。

IE では、GET, POST どちらを選択しても、
open の URL欄に記述されたデータは GET として、
send に記述されたデータは POST として受け取ります。
open のURL欄、send 両方記述していても、ちゃんとどちらも送信され、
サーバではそれぞれ区別して受け取ります。


Firefox では、GET にした場合、send に記述したデータは受け取れません。
しかし、POST では、send だけでなく、
open の URL欄に記述されたデータも受け取れます。
この時、サーバではそれぞれ区別して受け取ります。


さらに、IE では、GET だと日本語が文字化けしました。
以上の検証結果から、送信する時は、必ず POST にしておけば間違いないかなぁ~と思ったり。

というわけで、これらを使用したサンプルです。

name, body 欄に入力したデータを送信し、サーバ側の PHP で受け取り、
それに文字を追加したデータを返します、返ってきたデータを表示します。
name, body 以外に、ブラウザ名称を、
open の URL 欄に追加し、送信してみる。
ボタンを押すと動作します。
 結果 
name :
body :
  
XMLHttp の生成の為に以下の処理を作成しました。
 XMLHttp の生成 
function createXmlhttp() {
  var xmlhttp = false;
  try {
    xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
  } catch (e) {
  }
  if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
    xmlhttp = new XMLHttpRequest();
  }
  return xmlhttp;
}

サンプルでは、GET なのに send も送信したりというややこしいことはしていません。
 GET 送信 
function GET() {
  var xmlhttp = new createXmlhttp();
  var txt = new String();
  var frm = document.frm;

  for(var i = 0 ; i < frm.elements.length ; i++){
    if(!frm.elements[i].disabled){
      txt += "&";
      txt += frm.elements[i].name;
      txt += "=";
      txt += frm.elements[i].value;
    }
  }
  if(txt.length > 0){
    txt = txt.substring(1);
  }

  if (xmlhttp) {
    xmlhttp.open('GET', './sample/sample1.php?' + txt '&browser=' + navigator.appName);
    xmlhttp.onreadystatechange = function() {
      if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
        var disp = document.getElementById("disp");
        disp.innerHTML=xmlhttp.responseText;
      }
    }
    xmlhttp.setRequestHeader("Content-Type" , "application/x-www-form-urlencoded");
    xmlhttp.send(null);
  }
}

 POST 送信 
function POST() {
  var xmlhttp = new createXmlhttp();
  var txt = new String();
  var frm = document.frm;

  for(var i = 0 ; i < frm.elements.length ; i++){
    if(!frm.elements[i].disabled){
      txt += "&";
      txt += frm.elements[i].name;
      txt += "=";
      txt += frm.elements[i].value;
    }
  }
  if(txt.length > 0){
    txt = txt.substring(1);
  }

  if (xmlhttp) {
    xmlhttp.open('POST', './sample/sample1.php?browser=' + navigator.appName);
    xmlhttp.onreadystatechange = function() {
      if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
        var disp = document.getElementById("disp");
        disp.innerHTML=xmlhttp.responseText;
      }
    }
    xmlhttp.setRequestHeader("Content-Type" , "application/x-www-form-urlencoded");
    xmlhttp.send(txt);
  }
}

GET, POST どちらもですが、
  var txt = new String();
  var frm = document.frm;

  for(var i = 0 ; i < frm.elements.length ; i++){
    if(!frm.elements[i].disabled){
      txt += "&";
      txt += frm.elements[i].name;
      txt += "=";
      txt += frm.elements[i].value;
    }
  }
の箇所で、送信するデータを作成しています。
このままでは、"&name=xx&body=yy"のようになるので、
先頭の & をなくす為、
  if(txt.length > 0){
    txt = txt.substring(1);
  }
としています。

その後は、GET の場合は、以下のように open の URL欄に送信するデータを追加し、
send は 今まで通り null としています。
setRequestHeader も忘れず設定します。
  if (xmlhttp) {
    xmlhttp.open('GET', './sample/sample1.php?' + txt '&browser=' + navigator.appName);
    xmlhttp.onreadystatechange = function() {
      if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
        var disp = document.getElementById("disp");
        disp.innerHTML=xmlhttp.responseText;
      }
    }
    xmlhttp.setRequestHeader("Content-Type" , "application/x-www-form-urlencoded");
    xmlhttp.send(null);
  }

POST の場合は、以下のように open の URL欄に GET として送信するデータを追加し、
send は POST で送信するデータを追加しています。
ここでも setRequestHeader も忘れず設定します。
  if (xmlhttp) {
    xmlhttp.open('POST', './sample/sample1.php?browser=' + navigator.appName);
    xmlhttp.onreadystatechange = function() {
      if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
        var disp = document.getElementById("disp");
        disp.innerHTML=xmlhttp.responseText;
      }
    }
    xmlhttp.setRequestHeader("Content-Type" , "application/x-www-form-urlencoded");
    xmlhttp.send(txt);
  }

サーバ側では、以下のようにしました。
GET の name がセットされていたら、GET を受信したと判断し、
そうでなければ POST と判断して処理をわけました。
最後に、処理結果を出力しています。
 sample1.php 
<?php
  if(isset($_GET["name"])) {
    $text = "GET 送信 name : ".$_GET["name"].", body : ".$_GET["body"]." Browser : ".$_GET["browser"];
  }else{
    $text = "POST 送信 name : ".$_POST["name"].", body : ".$_POST["body"]." Browser : ".$_GET["browser"];
  }

  print $text;
?>

その処理結果をテキスト形式(responseText)で取得して、表示させています。