
ユーザー参加コンテンツで「ユーザーが自由にファイルをアップロードしたいです。画像とか。」とかを作る場合、Flash Player 9 以上、AS3 ならば FileReference.upload() を使ってファイルをアップロードします。
ただし色々 FileReference 系はややこしいので、注意すべき点がいっぱい。サーバーサイドとのやりとりを円滑に進めるためにも、ココでまとめているものは初期の段階でサーバーサイド担当者とやりとりできたらいいですね。
まず、FileReference.upload() の手順はこんな感じ。
var fileRef:FileReference = new FileReference();
fileRef.addEventListener(Event.SELECT, fileSelectedHandler);
fileRef.addEventListener(Event.OPEN, fileOpenHandler);
fileRef.addEventListener(ProgressEvent.PROGRESS, fileUploadProgressHandler);
fileRef.addEventListener(Event.COMPLETE, fileUploadedHandler);
fileRef.addEventListener(DataEvent.UPLOAD_COMPLETE, fileUploadResultHandler);
fileRef.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
fileRef.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
function fileSelectedHandler(event:Event):void
{
trace("SELECTED", fileRef.name, fileRef.size / 1024 + "KB");
// つづけてアップロードしちゃう
// ファイルサイズ制限持たせたい場合はここの前で FileReference.size を判別してエラー表示する
var request:URLRequest = new URLRequest("なんたら.php/.cfm/.pl");
// POST通信でなければならない
request.method = URLRequestMethod.POST;
// UPLOAD 開始。
// アップロードするファイルのキー名は、デフォルトが Filedata になります。
// 引数で変更可能。
fileRef.upload(request, "Filedata", false);
}
function fileOpenHandler(event:Event):void
{
// アップロード開始
trace("START");
}
function fileUploadProgressHandler(event:ProgressEvent):void
{
// アップロードのプログレスバー表示とかするときに
trace(event.bytesLoaded / event.bytesTotal * 100, "%");
}
function fileUploadedHandler(event:Event):void
{
// こちらからのアップロードが完了したとき
// エラーが出た時のタイミングによって何がおかしかったかを判別するときに使うぐらい?
trace("UPLOAD COMPLETE");
}
function fileUploadResultHandler(event:DataEvent):void
{
// fileUploadedHandler のあとに、サーバースクリプトを経て帰ってくるデータ
// サーバー側は必ず何か文字列でも XML でも何か返さなければならない
trace("FINISH" + event.data);
}
function ioErrorHandler(event:IOErrorEvent):void
{
// サーバーサイドスクリプトに Flash が到達できない場合
trace("IO ERROR");
trace(event.text);
}
function securityErrorHandler(event:SecurityErrorEvent):void
{
// セキュリティ的なエラーが出た場合
trace("SECURITY ERROR");
trace(event.text);
}
function clickHandler(event:MouseEvent):void
{
// ボタンをクリックしてアップロードする画像を選ぶためのファイルブラウザを開く
var filters:Array = [];
filters.push(new FileFilter("Images (*.jpg, *.jpeg, *.gif, *.png)", "*.jpg; *.jpeg; *.gif; *.png" ));
fileRef.browse(filters);
}
var btn:Sprite = new Sprite();
btn.addEventListener(MouseEvent.CLICK, clickHandler);
btn.graphics.beginFill(0xff0000);
btn.graphics.drawRect(0, 0, 100, 100);
btn.graphcis.endFill();
addChild(btn);
ちなみにセキュリティ的に無理なのかな?とおもっていましたが、 FileReference.upload() が実行されるタイミングは、「ボタンのクリック直後でなければならない」ということは無いようです。
FileReference.browse() の実行は「ボタンのクリック直後でなければならない」です。
サーバー担当とのやりとりで気をつける点
1. Basic 認証が効いているとダメ。
Adobe のヘルプに記載有り。仕様です。
http://livedocs.adobe.com/flex/3_jp/langref/flash/net/FileReference.html#upload()
認証が効いていると IO_ERROR となります。リリース前のテスト中は認証をかけておきたいという場合、開発機やテスト環境からのホストは認証がかからないようにする必要があります。
このあたりが参考になる気がします。
Basic 認証をかけるが,特定のホストは認証なしで通過させる方法 - memo.xight.org
http://memo.xight.org/2004-07-18-2
特定ディレクトリの認証をはずす方法 | RontanBlog
http://rontan.sakura.ne.jp/2009/08/tips_htaccess_basic_authorize/
floatingdays: Apacheで特定の URLのみ認証をかけない方法
http://fdays.blogspot.com/2008/07/apache-url.html
2. HTTPS だと問題が出る場合あり。通信はできるだけ HTTP で。
URL 内に HTTPS のポート番号(443)を記述すると動作する可能性があるらしい。
https://www.******.com:443/upload.php
AS2 だとコレでいけるけど、AS3 だといけないという情報があったりなかったり。。。
SSL環境でFlashからのファイルアップがうまくいかない問題(FF) | RontanBlog
http://rontan.sakura.ne.jp/2009/08/tips_file_reference_upload/
Firefox と相性が悪かったり。。
AIRLife.net: FileReference.upload()の宛先がhttpsだとFirefoxでは失敗する
http://blog.air-life.net/2008/06/firefoxfilereferenceuploadga.html
FlashでSSLの時に起きる問題|Web制作で今すぐ使えるテクニック集
http://ameblo.jp/linking/entry-10094942703.html
3. サーバーは受信完了したら、何か出力する。
確認出来ていませんが、DataEvent.UPLOAD_COMPLETE が取れない場合があったりする、ということかもしれません。
成功したら「0」とかレスポンスするだけでもいいので完了したら echo("0"); とするだけでもいいかもしれません。
FileReference.uploadにまけるな! - FLEXTIME FLASH
http://graphicker.jp/flextime/flash/archives/2008/05/as-upload.html
↑HTTPS は 433 としてますが誤植かも。(正しくは 443)
4. クロスドメインポリシーファイル必須。
セキュリティーエラーでます。
クロスドメインポリシーファイルを置いてクロスドメインを許可しましょう。
PHP でプロキシすればいける?
YOPPA BLOG ≫ Flash(AS3)でcrossdomain.xml無しにクロスドメインにアクセスする
http://yoppa.org/rsd.php?itemid=691
5. その他サーバー環境などに応じて対応
色々なかなかやっかいで大変ですよねぇ。
---
Flash Player 10 以降と FileReference
ちなみに FlashPlayer 10 コンテンツを作るときならば、FileReference.browse() で呼び出したデータ(たとえば画像)のバイナリを FileReference.load() と FileReference.data でとることができ、それを URLVariables のパラメータにぶっ込むことができるので、通信では FileReference を使うことがなく、もう少しシンプルに考えられるかもしれません。
Flash Player 10 のローカルファイルアクセス機能 (FileReference クラス) - akihiro kamijo
http://blogs.adobe.com/akamijo/archives/2008/07/flash_player_10_5.html
2009-09-04 - よせ とうふ [as3]FileReferenceのお話
http://d.hatena.ne.jp/folderol/20090904#1252076206

