Skip navigation
Currently Being Moderated

Displaying a progress dialog before calling URLLoader.load in flex?

Jan 9, 2013 6:47 AM

Tags: #flex #asynchronous #urlloader #popup #actionscript_3 #synchronous

I'm developing a flex application (run in web browser), that lets the user load a number of files and then sends them all to a server in one single multipart/form-data request.

My problem is this:
For security reasons, flash requires that the user initiates the URLLoader.load action by clicking on a button. That's ok, the user clicks the save button in the application and off we go.
Unfortunately, the uploading part of the request doesn't seem to be asynchronous, but only the downloading part. The data can be any size since the user can add an arbitrary number of files, so the upload can take a while to complete.

In an ideal world I would do something like this in the click handler of the save button:

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

Unfortunately this will result in the progressdialog being shown after the upload finishes. So, can I defer the upload start until the popup has been shown, like this?

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

Turns out I can't do this either, because of the security reasons mentioned above. This will throw a SecurityError: Error #2176.

Basically the problem is

  1. A popup won't be visible until the code in the current frame has completed
  2. URLLoader.load blocks until the upload part of the request is completed
  3. The popup arrives too late, since the time consuming part is already over.
  4. I can't wait for the popup, since the load action has to be initiated by the user click.

Is there any way whatsoever to work around this limitation?

Here is a small application that illustrates the problem. Button two and three will throw the 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 {
               popup = PopUpManager.createPopUp(this, ProgressDialog, true);
               doLoad();
          }

          protected function sendWithSetTimeoutButton_clickHandler(event:MouseEvent):void {
               popup = PopUpManager.createPopUp(this, ProgressDialog, true);
               setTimeout(doLoad, 200); // This will throw SecurityError
          }

          protected function sendWithCallLaterButton_clickHandler(event:MouseEvent):void {
               popup = PopUpManager.createPopUp(this, ProgressDialog, true);
               callLater(doLoad); // This will throw SecurityError
          }

          private function doLoad():void {
               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);
          } 

          protected function loaderComplete(event:Event):void {
               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>
 

More Like This

  • Retrieving data ...

Bookmarked By (0)

Answers + Points = Status

  • 10 points awarded for Correct Answers
  • 5 points awarded for Helpful Answers
  • 10,000+ points
  • 1,001-10,000 points
  • 501-1,000 points
  • 5-500 points