プログラミング工房
TOP
Flex基本
開発環境 JavaScript連携 PHP連携1 PHP連携2(AMFPHP) ウィンドウ ボタンスキン 矩形スキン ローカルファイル(テキスト) F5等の対策 ローカルファイル(イメージ) ダウンロード、アップロード 1枚の画像のカラーを変更 時間のかかる計算処理 外部SWFの読込み
Flexで3D
Flexだけで3D Papervision3Dを使ってみる 3Dオブジェクト カメラ、前後判定の工夫しました 自由な形状を作成
Flexでクラス
Class1(白黒ゲームの盤) Class2(白黒ゲームのプレイヤー) Class3(プレイヤーを外部SWF)
PHP
共通関数1
Flexの作品
お問合せの説明 サンプルのソース表示の説明 分子構造の表示(PDBファイル) マンデルブロ集合の画像作成 swf参加型白黒ゲーム(Reversi) ストップウォッチ WEB素材
AIR
AIRを使ってみる ソースファイルのHTML変換を作る
etc.
マンデルブロ集合のギャラリー ジュリア集合のギャラリー wonderflを使ってみました お問合せ

Flex4基本-ダウンロード、アップロード

■2011.03.08:作成
■2011.03.09:URLLoader - FileReference.saveでダウンロードに注意追記
サンプル サンプルのソース
サンプルのアップロードはコメントアウトしています。

サーバに対するファイルのダウンロード、アップロード

Flex4とPHPを利用すしてサーバに対するファイルのダウンロード、アップロードを行います。
ダウンロード、アップロードの方法をいくか試してみます。

Flex内で使用している変数"strPhpUrl"は Flex4基本-PHP連携1:PHPのパスに関してを見てください。

navigateToURLでダウンロード

ダウンロードで一番簡単なのは"navigateToURL"だと思います。
HTNLの"a"タグと同じ動きです。

ダウンロードする対象がHTMLや画像ファイルがならばブラウザが開き、CSVファイルならEXCELで開きます。 (ローカルのPCの設定により動きは異なります)
定義されていない拡張子のファイルは「ダウンロード」になります。
//navigateToURLでダウンロード----------------------------------------
private function onGetURL(event:Event):void {
    var req:URLRequest = new URLRequest(strPhpUrl + strDownFile);
    navigateToURL(req, "_blank");
}

FileReference.downloadでダウンロード

ダウンロードで一番よく使われるのは「FileReference.download」だと思います。

ダウンロードの成功(onDownComp)、失敗(onDownError)時のイベント関数を指定して、
サーバのファイル名とダウンロードの初期ファイル名を指定して実行するだけです。
//FileReference.downloadでダウンロード------------------------------
private function onDownload(event:Event):void {
    downloadURL = new URLRequest();
    downloadURL.url = strPhpUrl + strDownFile;
    var fileName:String = strDownFile.substring(strDownFile.lastIndexOf('/')+1);
    filRef = new FileReference();
    filRef.addEventListener(Event.COMPLETE, onDownComp);
    filRef.addEventListener(IOErrorEvent.IO_ERROR, onDownError);
    filRef.download(downloadURL, fileName);
}
private function onDownComp(event:Event):void {
    //Alert.show("ファイルをダウンロードしました。","ServerFile");
}
private function onDownError(event:IOErrorEvent):void {
    Alert.show("ダウンロードに失敗しました。","ServerFile");
}

URLLoader - FileReference.saveでダウンロード

URLLoaderとFileReference.saveを利用してダウンロード出来ます。
 注意:URLLoaderでZIPやTEXT等は問題ありませんが、PHP等のWEBで実行できる
    ファイルはPHPの実行結果がダウンロードされてしまいます。

URLLoaderの使い方は「FileReference.download」と同じように使えますが、ファイルの
データをローカルファイルでなく、Flexのメモリー上(この例では変数"gbytArra")に
読み込むことが出来ます。
読み込んだ内容を「FileReference.save」でローカルに保存すればダウンロード出来ます。
(「FileReference.save」の使用方法は Flex4基本-ローカルファイル(テキスト) を参考にして下さい)

ファイルの内容が一旦Flexのメモリー上に展開されますから漢字コード・改行コードの変換等を
行うことの可能です。

注意:
URLLoaderとFileReference.saveの間に「Alert.show」でダウンロードの確認を行っています。
この余分な処理は「必要」です。
「FileReference」はセキュリティの関係でマウスイベント等のユーザが直接行ったイベント内で しか実行することが出来ません。
 今回はURLLoaderの完了イベント(ユーザ直接イベントではない)で「FileReference」を
実行できません。この為「Alert.show」のOKボタンのイベント(ユーザが直接行ったイベント)
で「FileReference.save」を実行しています。
//URLLoader - FileReference.saveでダウンロード---------------------
private function onDownUrllo(event:Event):void {
    var urlLoader:URLLoader = new URLLoader();
    urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
    urlLoader.addEventListener(Event.COMPLETE, onCompUrlLoad);
    urlLoader.addEventListener(IOErrorEvent.IO_ERROR, onErrUrlLoad);

    urlLoader.load(new URLRequest(strPhpUrl + strDownFile));
}
private function onCompUrlLoad(event:Event):void {
    gfileName = strDownFile.substring(strDownFile.lastIndexOf('/') + 1);
    var urlLoader:URLLoader = event.currentTarget as URLLoader;
    gbytArra = urlLoader.data as ByteArray;
    Alert.show("ファイルをダウンロードしてよいですか?",
            "ServerFile", Alert.YES | Alert.NO, this, alertClickDown);
}
private function onErrUrlLoad(e:IOErrorEvent):void {
    Alert.show("ダウンロードに失敗しました。","ServerFile");
               :
//FileReference.save処理共通---------
private function alertClickDown(evt:CloseEvent):void {
    if (evt.detail == Alert.YES) {  //保存OK
        filRef = new FileReference();
        filRef.addEventListener(Event.COMPLETE, onFileSave);
        filRef.addEventListener(IOErrorEvent.IO_ERROR, onFileSaveErr);
        filRef.save(gbytArra, gfileName);
    }
}
//保存完了
private function onFileSave(e:Event):void {
    Alert.show("ローカルファイルへの保存しました。", "ServerFile");
}
//保存エラー
private function onFileSaveErr(e:IOErrorEvent):void {
    Alert.show("ローカルファイルへの保存を失敗しました。\n"+e.toString(),
                "ServerFile");
}

PHP(AMFPHP) - FileReference.saveでダウンロード

「URLLoader」の代わりに「PHP(AMFPHP)」を利用してサーバファイルをFlexのメモリ上
(この例では変数"gbytArra")に読み込みます。 (Flex4基本-PHP連携2(AMFPHP)を参考)

以降は「URLLoader - FileReference.saveでダウンロード」と同じです。
(「Alert.show」の注意書きも含めて)

PHPからFlexの通信でバイナリデータがうまくいかないのでPHP側で「bin2hex」を利用して
バイナリデータを16進文字データに変換しています。
逆変換用にFlex側で「hex2bin」関数を用意しています。
//PHP - FileReference.saveでダウンロード------------------------
private function onPhpFileRefSave(event:Event):void {
    //PHPから戻ったときの関数
    var responder:Responder = new Responder(fncPhpFileGet, onPhpFault);
    var connection:NetConnection = new NetConnection();
    //実行するPHP
    connection.connect(strPhpUrl+"Gateway.php");
    connection.objectEncoding = ObjectEncoding.AMF3;
    // PHPのService.FileGetメソッドを呼び出す
    connection.call("Service.FileGet", responder,strDownFile);
}

// ファイルデータ取得成功
private function fncPhpFileGet(arrDat:Array):void {
    if (arrDat[0] != "") {
        Alert.show("エラー:" + arrDat[0], "ServerFile");
        return;
    }
    gfileName = strDownFile.substring(strDownFile.lastIndexOf('/') + 1);
    //var bytArra:ByteArray = arrDat[1].data as ByteArray;
    gbytArra = hex2bin(arrDat[1]);
    Alert.show("ファイルをダウンロードしてよいですか?",
            "ServerFile", Alert.YES | Alert.NO, this, alertClickDown);
}
                 :
private function hex2bin(strData:String):ByteArray {
    var retByteArr:ByteArray = new ByteArray();
    var i:Number;
    for (i = 0; i < strData.length - 1; i += 2) {
        var strHex:String = "0x" + strData.substr(i, 2);
        retByteArr.writeByte(int(strHex));
    }
    return retByteArr;
}

サーバ側のService.phpのFileGet関数
指定ファイルのファイルを読み込み、「bin2hex」でバイナリーファイルを16進文字データに
変換しFlex側に送っています。

この方法ならDB上のデータ等、実際ファイルを作成しなくてもPHP上でデータを作成すれば
その作成データのダウンロードが可能です。
    public function FileGet($fileNam){

        //PHPでエラーが発生したときエラーメッセージをセット
        $err = "";
        $leng = 0;
        $FileData="";
        //$FileData = new ByteArray("");
        try {
            $handle = fopen($fileNam, "rb");
            if ($handle === FALSE) {
                $err = "ファイルがオープン出来ません。";
            }
            else {
                $leng=filesize($fileNam);
                $FileData = bin2hex(fread($handle, filesize($fileNam)));
                //$FileData = new ByteArray( fread($handle, filesize($fileNam)));
                fclose($handle);
            }
        } catch (Exception $e) {
            $err = $e->getMessage();
        }
        $arrData = array($err, $FileData);

        return $arrData;
    }

FileReference.upload - PHPでアップロード

今度はアップロードです。
FileReference.uploadとPHPを利用する方法が、ファイルのアップロードの一般的なものと思います。
Flex4基本-ローカルファイル(テキスト) の読み込みとほぼ同じです、「filRef.load();」の代わりに「filRef.upload(uploadURL);」 を使用します。(uploadURLがサーバ側で実行されるPHP名)
//FileReference.upload - PHPでアップロード------------------------
private function onUploadPhp(event:Event):void {

    uploadURL = new URLRequest();

    //ファイルのアップロード先URL
    uploadURL.url = strPhpUrl + "upload.php";
    filRef = new FileReference();
    filRef.addEventListener(Event.SELECT, selectHandler);
    filRef.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
    filRef.addEventListener(Event.COMPLETE, completeHandler);
    filRef.browse();
}
//ファイルが選択されたとき
private function selectHandler(event:Event):void {
    var file:FileReference = FileReference(event.target);
    filRef.upload(uploadURL);
}
//アップロード完了したとき
private function completeHandler(event:Event):void {
    Alert.show("アップロード完了","ServerFile");
}
//アップロードエラー
private function ioErrorHandler(event:IOErrorEvent):void {
    Alert.show("アップロード失敗","ServerFile");
}

サーバ側のupload.phpの処理(このPHPはAMFPHPを使用していません)
アップされた(テンポラリ)ファイルを正式の所に移動しています。
<?php
//アップされたファイルを保存する。

$fname = "file/" . $_FILES['Filedata']['name'];
move_uploaded_file( $_FILES['Filedata']['tmp_name'] ,  $fname );

exit;
?>

FileReference.load - PHP(AMFPHP)でアップロード

ローカルファイルの読み込み(Flex4基本-ローカルファイル(テキスト) の読み込み参照)
で、まずFelxのメモリ上にファイルデータ読み込みます。
次にサーバのPHP(AMFPHP)(Flex4基本-PHP連携2(AMFPHP)を参考)にファイルデータを送ります。

一旦Flex上にデータを持つので「同じファイル名があるとき」等の対応も簡単に行えます。

また、ダウンロードと異なりFlexからPHPではバイナリデータも問題ないので バイナリデータ(ByteArray)のまま送信できます。
//FileReference.load - PHPでアップロード----------------------------
private function onLoadPhp(event:Event):void {
    filRef = new FileReference();
    var FilterAll:FileFilter = new FileFilter("全て(*.*)", "*.*");
    filRef.browse([FilterAll]);
    filRef.addEventListener(Event.SELECT, onFileSelected);
}
private function onFileSelected(e:Event):void {
    filRef.addEventListener(Event.COMPLETE, onFileLoaded);
    filRef.addEventListener(IOErrorEvent.IO_ERROR, onFileLoadErr);
    filRef.load();
}
//読み込み完了
private function onFileLoaded(e:Event):void {
    //PHPに送信するデータセット
    var barrDat:ByteArray = e.target.data;
    var strFileName:String ="file/"+ e.target.name;
    //PHPから戻ったときの関数
    var responder:Responder = new Responder(fncPhpFilePut, onPhpFault);
    var connection:NetConnection = new NetConnection();
    //実行するPHP
    connection.connect(strPhpUrl+"Gateway.php");
    connection.objectEncoding = ObjectEncoding.AMF3;
    connection.call("Service.FilePut", responder,strFileName,barrDat);
}
// サーバに書き込み成功
private function fncPhpFilePut(arrDat:Array):void {
    if (arrDat[0] != "") {
        Alert.show("エラー:" + arrDat[0], "ServerFile");
        return;
    }
    Alert.show("サーバに書き込み成功ました。\n",
               "ServerFile");
}
//書き込みエラー
private function onFileLoadErr(e:IOErrorEvent):void {
    Alert.show("ロサーバに書き込を失敗しました。\n"+e.toString(),
               "ServerFile");
}

サーバ側のService.phpのFilePut関数(AMFPHPを利用)
指定ファイルを書き込みます、Flex側で「ByteArray」で定義しているときは
「$barrDat->data」が対象のデータです。

この形式ならデータをファイル使用しないでDB等に直接保存することも可能です。
    public function FilePut($strFileName,$barrDat) {
        $err="";
        $fp = fopen($strFileName, 'wb');
        if ($fp){
            if (flock($fp, LOCK_EX)){
                if (fwrite($fp,  $barrDat->data) === FALSE){
                    $err='ファイル書き込みに失敗しました';
                }

                flock($fp, LOCK_UN);
            }else{
                $err='ファイルロックに失敗しました';
            }
            fclose($fp);
        }else{
            $err='ファイル書き込みに失敗しました';
        }
        $arrData = array($err);
        return $arrData;
    }

プログラミング工房