2009-08-09

【AS3.0】XMLの送受信【PHP】

GDP企画の際必要になった,ActionScriptを使ったXMLの送受信.

Flash/AIRとPHP間でXMLのやりとりをするのに使った.



試行錯誤した結果,結局こんな感じでうまくいくことがわかった.

基本的に,URLRequestで送信データ,およびその設定を行い,

URLLoaderでリクエスト(送信),Completeイベントでphpからのレスポンスが帰ってくる仕組み.

package {
import flash.events.Event;
import flash.events.ProgressEvent;
import flash.events.IOErrorEvent;
import flash.events.EventDispatcher;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.net.URLRequestMethod;
import flash.utils.ByteArray;

/**
* ConnectPHP
* @auther kusamochi
*/
public class ConnectPHP extends EventDispatcher {
public static const COMPLETE:String = "complete";
public static const IO_ERROR:String = "io_error";
public static const PROGRESS:String = "progress";
public static const FAILED:String = "failed";

private var _urlRequest:URLRequest;
private var _result:XML;

private var urlLoader:URLLoader;

// コンストラクタ
public function ConnectPHP() {
}

// XMLの送信
public function sendAndLoad_XML(url:String, xml:XML):void {
// 送信するデータを設定
_urlRequest = new URLRequest(url);
_urlRequest.contentType = "text/xml";
_urlRequest.data = xml.toXMLString();
// データはPOSTで送信
_urlRequest.method = URLRequestMethod.POST;

// URL
urlLoader = new URLLoader();
urlLoader.dataFormat = URLLoaderDataFormat.TEXT;

// イベントリスナー登録
urlLoader.addEventListener(Event.COMPLETE, completeHandler);
urlLoader.addEventListener(ProgressEvent.PROGRESS, progressHandler);
urlLoader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
urlLoader.load(_urlRequest);
}

// データロード完了のイベントリスナー
private function completeHandler(event:Event):void {
urlLoader.removeEventListener(Event.COMPLETE, completeHandler);
urlLoader.removeEventListener(ProgressEvent.PROGRESS, progressHandler);
urlLoader.removeEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
// reusltに格納
try {
_result = new XML(event.target.data);
}
catch(error:TypeError) {
// イベントをブロードキャスト
dispatchEvent(new Event(FAILED));
return;
}

// イベントをブロードキャスト
dispatchEvent(new Event(COMPLETE));
}

// 送信中に一定間隔で発生するイベントリスナー
private function progressHandler(event:ProgressEvent):void {
// イベントをブロードキャスト
dispatchEvent(new ProgressEvent(PROGRESS));
}

// 送信エラーのイベントリスナー
private function ioErrorHandler(event:IOErrorEvent):void {
urlLoader.removeEventListener(Event.COMPLETE, completeHandler);
urlLoader.removeEventListener(ProgressEvent.PROGRESS, progressHandler);
urlLoader.removeEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
// イベントをブロードキャスト
dispatchEvent(new IOErrorEvent(IO_ERROR));
}

// 参照削除
public function deleteReference():void {
if(urlLoader) {
urlLoader.addEventListener(Event.COMPLETE, completeHandler);
urlLoader.addEventListener(ProgressEvent.PROGRESS, progressHandler);
urlLoader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
urlLoader.close();
}
_urlRequest = null;
_result = null;
}

// getter //////////////////////////////////////////////////////
// result
public function get result():XML {
if(_result) return _result;
else        return null;
}
}
}

ポイントは,Content-typeを"text/xml"にして,xmlのStringを送信すること.

当初,Content-typeを"application/octet-stream"(バイナリデータの意)として,

XMLをBinaryArrayで送っていたけど,

それだと送信先でヘッダーに文字化けが起きる.



ちなみに,PHP側では,

$inputStr = file_get_contents("php://input");
$xml = simplexml_load_string($inputStr);

print "<result>";
// Flash側に送りたいデータをほげほげ
print "</result>";

というように,file_get_contents("php://input")で,

生データを丸ごと読みこんでPHPのXMLクラスに変換.

Flash側に送りたいXMLは,PHP自身にタグをprintすればいい.

0 件のコメント: