0

我正在开发一个 flex 应用程序(在 Web 浏览器中运行),它允许用户加载许多文件,然后在一个单一的 multipart/form-data 请求中将它们全部发送到服务器。

我的问题是:
出于安全原因,flash 要求用户通过单击按钮来启动 URLLoader.load 操作。没关系,用户单击应用程序中的保存按钮,然后我们就走了。
不幸的是,请求的上传部分似乎不是异步的,而只是下载部分。数据可以是任意大小,因为用户可以添加任意数量的文件,因此上传可能需要一段时间才能完成。

在一个理想的世界里,我会在保存按钮的点击处理程序中做这样的事情:

PopupManager.createPopup(this, ProgressDialog, true);
doUpload();

不幸的是,这将导致在上传完成后显示进度对话框。那么,我可以像这样将上传开始推迟到弹出窗口显示之前吗?

PopupManager.createPopup(this, ProgressDialog, true);
setTimeout(doUpload, 100);

结果我也不能这样做,因为上面提到的安全原因。这将引发 SecurityError:错误 #2176。

基本上问题是

  1. 在当前帧中的代码完成之前,弹出窗口将不可见
  2. URLLoader.load 阻塞,直到请求的上传部分完成
  3. 弹出窗口来得太晚了,因为耗时的部分已经结束。
  4. 我等不及弹出窗口了,因为加载操作必须由用户单击启动。

有什么办法可以解决这个限制吗?

这是一个说明问题的小应用程序。按钮二和三将抛出 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>
4

0 回答 0