fileReferenceを使ってみた

ファイルのアップロードに関してのメモ。

fileの選択、アップロードをするコード。
また、アップロード中は画面をロックするようにしている。

※ここではサーバサイドの実装はかいてません
 テストする際は重い目のファイルをアップロードすると試せれます。

サンプルコード
  • LockWindow.mxml(画面lock中に表示されるパネル)
<?xml version="1.0"?>
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
    width="300" height="160" title="upload中">
    <mx:VBox>
        <mx:Label text="現在upload中です。しばらくお待ち下さい。" />
    </mx:VBox>
</mx:TitleWindow>
<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="init()">
<mx:Script>
<![CDATA[
    import LockWindow;

    private var file:FileReference;
    private var sfile:FileReference;
    private var lock_window:LockWindow;

    private function init():void {
        file = new FileReference();
        sfile = new FileReference();
        lock_window = new LockWindow();
    }

    private function searchFile():void {
        file.browse();
        file.addEventListener(Event.SELECT, selectHandler);
    }

    private function selectHandler(event:Event):void {
        sfile = FileReference(event.currentTarget);
        filename.text = sfile.name;
    }

    private function uploader(url:String):void {
        var request:URLRequest = new URLRequest();
        request.url = url;
        request.method = URLRequestMethod.POST;
        sfile.upload(request);

        //upload flow handler
        sfile.addEventListener(Event.OPEN, this.openHandler);
        sfile.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA, this.completeHandler);

        //upload error handler
        sfile.addEventListener(IOErrorEvent.IO_ERROR,
            function (e:IOErrorEvent):void {
                trace("IOError");
        });

        sfile.addEventListener(SecurityErrorEvent.SECURITY_ERROR,
            function (e:SecurityErrorEvent):void {
                trace("SecurityError");
        });
    }
private function openHandler(e:Event):void {
        PopUpManager.addPopUp(this.lock_window, this, true);
        PopUpManager.centerPopUp(lock_window);
    }

    private function completeHandler(e:DataEvent):void {
        PopUpManager.removePopUp(this.lock_window);
        (e.data)
            ? trace("complete")
            : trace("upload failed");
    }
]]>
</mx:Script>
    <mx:HBox>
        <mx:TextInput id="filename" />
        <mx:Button label="file選択" click="searchFile()" />
        <mx:Button label="FileUpload" click="uploader('upload先のURL')" />
    </mx:HBox>

</mx:Application>
ファイルの選択
    private function searchFile():void {
        file.browse();
        file.addEventListener(Event.SELECT, selectHandler);
    }

    private function selectHandler(event:Event):void {
        sfile = FileReference(event.currentTarget);
        filename.text = sfile.name;
    }
  1. file.browse()でローカルのファイルを選択するwindowを開いている。
  2. ファイルを選択された時のイベントを登録。
  3. 選択されたイベントが発生したらファイル名をfilenameに表示。
パラメータの送信

Cookieを送信してくれない。
そのため、Cookieを送信したい場合はjsを使ってcookieを取得してPOSTで送信する必要がある。
詳細については前のエントリーを参考にしてください。

sfile.upload(request, "file");

こんな感じで第二引数を指定してやると
"file"というパラメータ名でサーバサイドに渡される。
ちなみにdefaultでは"Filedata"。

メソッドと無名関数の変数の参照の違い

無名関数にすると"this"がglobalになるってことに気づかなくてハマった。
くそー。。。。

ちなみにこんな感じ。
[]内のプロパティをtraceしてみた。

  • メソッドとして定義
sfile.addEventListener(Event.OPEN, this.openHandler);

・・・
private function openHandler(e:Event):void {
        PopUpManager.addPopUp(this.lock_window, this, true);
        PopUpManager.centerPopUp(lock_window);
    }

[this] : main0
[stage] : [object Stage]
[root] : [object _main_mx_managers_SystemManager]
[lock_window] : LockWindow19
[this.lock_window] : LockWindow19

  • 無名関数として定義
sfile.addEventListener(Event.OPEN, function (e:Event):void {
        PopUpManager.addPopUp(this.lock_window, this, true);
        PopUpManager.centerPopUp(lock_window);
});

[this] : [object global]
[stage] : [object Stage]
[root] : [object _main_mx_managers_SystemManager]
[lock_window] : LockWindow19
[this.lock_window] : undefined

やっぱFlexおもしれーなー