ユーザーが多数のファイルをロードし、それらすべてを1回のマルチパート/フォームデータリクエストでサーバーに送信できるようにするフレックスアプリケーション(Webブラウザーで実行)を開発しています。
私の問題は次のとおりです
。セキュリティ上の理由から、フラッシュでは、ユーザーがボタンをクリックして URLLoader.load アクションを開始する必要があります。ユーザーがアプリケーションの保存ボタンをクリックすると、開始します。
残念ながら、リクエストのアップロード部分は非同期ではなく、ダウンロード部分のみのようです。ユーザーは任意の数のファイルを追加できるため、データは任意のサイズになる可能性があるため、アップロードが完了するまでに時間がかかる場合があります。
理想的な世界では、保存ボタンのクリック ハンドラーで次のようなことを行います。
PopupManager.createPopup(this, ProgressDialog, true);
doUpload();
残念ながら、これにより、アップロードの完了後に進行状況ダイアログが表示されます。では、このようにポップアップが表示されるまでアップロードの開始を遅らせることはできますか?
PopupManager.createPopup(this, ProgressDialog, true);
setTimeout(doUpload, 100);
上記のセキュリティ上の理由から、これもできないことがわかりました。これにより、SecurityError: エラー #2176 がスローされます。
基本的に問題は
- 現在のフレームのコードが完了するまで、ポップアップは表示されません
- URLLoader.load は、リクエストのアップロード部分が完了するまでブロックします
- 時間のかかる部分はすでに終わっているため、ポップアップの到着が遅すぎます。
- ユーザーのクリックによって読み込みアクションを開始する必要があるため、ポップアップが待ちきれません。
この制限を回避する方法はありますか?
この問題を説明する小さなアプリケーションを次に示します。ボタン 2 と 3 は SecurityError をスローします。
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="419" height="250">
<fx:Script>
<![CDATA[
import mx.core.IFlexDisplayObject;
import mx.managers.PopUpManager;
private var urlLoader:URLLoader;
private var popup:IFlexDisplayObject;
protected function sendNowButton_clickHandler(event:MouseEvent):void {
trace(">> URLLoaderSendTest.sendNowButton_clickHandler(event)");
popup = PopUpManager.createPopUp(this, ProgressDialog, true);
doLoad();
trace("<< URLLoaderSendTest.sendNowButton_clickHandler(event)");
}
protected function sendWithSetTimeoutButton_clickHandler(event:MouseEvent):void {
trace(">> URLLoaderSendTest.sendLaterButton_clickHandler(event)");
popup = PopUpManager.createPopUp(this, ProgressDialog, true);
setTimeout(doLoad, 200);
trace("<< URLLoaderSendTest.sendLaterButton_clickHandler(event)");
}
protected function sendWithCallLaterButton_clickHandler(event:MouseEvent):void {
trace(">> URLLoaderSendTest.sendWithCallLaterButton_clickHandler(event)");
popup = PopUpManager.createPopUp(this, ProgressDialog, true);
callLater(doLoad);
trace("<< URLLoaderSendTest.sendWithCallLaterButton_clickHandler(event)");
}
private function doLoad():void {
trace(">> URLLoaderSendTest.doLoad()");
var bytes:ByteArray = new ByteArray();
bytes.writeInt(1);
var request:URLRequest = new URLRequest("http://localhost/test/");
request.method = URLRequestMethod.POST;
request.contentType = "multipart/form-data";
request.data = bytes;
urlLoader = new URLLoader();
urlLoader.addEventListener(Event.COMPLETE, loaderComplete);
urlLoader.load(request);
trace("<< URLLoaderSendTest.doLoad()");
}
protected function loaderComplete(event:Event):void {
trace(">> URLLoaderSendTest.loaderComplete(event)");
PopUpManager.removePopUp(popup);
}
]]>
</fx:Script>
<s:Button id="sendNowButton" x="10" y="10"
label="Send now"
click="sendNowButton_clickHandler(event)"/>
<s:Button id="sendWithsetTimeoutButton" x="10" y="40"
label="Send with setTimeout"
click="sendWithSetTimeoutButton_clickHandler(event)"/>
<s:Button id="sendWithCallLaterButton" x="10" y="70"
label="Send with callLater"
click="sendWithCallLaterButton_clickHandler(event)"/>
</s:Application>