Tracking Progress of a Server-Side Action in Flash/Flex

The ProgressBar component in Flash and Flex can easily be used to indicate the progress of a file download. Here, we'll use a simple method to display the progress of some other server-side action, such as parsing a large file.

The Problem: Determining Progress

I'm working on a project where a large CSV file needs to be parsed into the database. The files are relatively large, reaching 7 MB and 7000 records. Needless to say, parsing takes some time and I never like to leave users staring at an uninformative loading animation for more than ten seconds.

So I need to have the server give the Flash client some indication of progress.

The Solution: Fake Download Progress

The easiest way to get the progress of the server-side action is to fake a download. Basically, what happens is we send an HTTP header telling the Flash client that the size of the file is 100 bytes. Then we proceed to print out 100 "x" characters at 1 byte each.

Flash/Flex's URLLoader will read the progress and fire appropriate ProgressEvents so you can hook it into a progress bar. On the Flash side it's exactly the same as indicating the progress of downloading a file.

The Code

There are some little tricks in the details so I've included the important bits of server-side code. These examples are in PHP.

// turn off error reporting since it could pollute the output
error_reporting(0);
 
// send our fake Content-Length header
header("Content-Length: 100");
 
...
 
$handle = fopen($filePath, 'r');
$bytesTotal = filesize($filePath);
 
// the amount of progress written, from 0 to 100
$progressWritten = 0;
 
while (!feof($handle))
{
  // reset the time limit. otherwise the script will time out before
  // parsing of larger files is complete
  set_time_limit(30);
 
  // read a CSV record from the file
  $record = fgetcsv($handle, 4096);
 
  // do your parsing here
  parseRecord($record);
 
  // calculate the actual progress from 0 to 100
  $progress = floor(100 * ftell($handle) / $bytesTotal);
 
  // print out one 'x' each time another percent of the file is read
  while ($progress > $progressWritten)
  {
    echo 'x';
 
    // flush the output buffer
    ob_flush();
    flush();
 
    $progressWritten++;
  }
}

One of the important methods in here is ftell which indicates the position of the pointer in the file handle. This and filesize allow us to calculate the progress of the parse job.

Depending on the job whose progress your indicating, you might use some other way of calculating progress.

Another thing to note are the calls to ob_flush and flush. These methods ensure that output is sent to the client. Without them, no data is sent until our entire row of little x's loads and we get no indication of progress.

Finally, the use of the loop to print out x's is also important. It ensures that if two or more percentage points of progress are made, all the x's get printed.

Caveat: No Direct Feedback from the Script

In the script above, we turn off error reporting because if an error were to occur, it would probably print out more than 100 bytes worth and make it look like the action completed. We also need to ensure that nothing else is printed to the output via print, echo, etc.

The need to turn off all output brings up a notable limitation of this method. We can't return any useful output to the Flash client like we might normally do. For example, if there were parsing errors we need to find some other way to report them.

Script Feedback Workaround

For my project I used a token system to download a parsing report from the server. The steps here are as follows:

  1. Flash client acquires a parsing job token from the server.
  2. Flash client starts the job, sending the token as a GET or POST parameter. The server-side script reports the parsing progress so it can be displayed in a progress bar.
  3. When parsing is complete, the Flash client requests the parsing report associated with the token.

This is obviously a bit more work than printing out parsing errors as they occur. However, it's a clean way to work around the problem of restricted output.

Comments

Post new comment

The content of this field is kept private and will not be shown publicly.
If you have a Gravatar account, used to display your avatar.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • You can enable syntax highlighting of source code with the following tags: <code>. Beside the tag style "<foo>" it is also possible to use "[foo]".
  • Lines and paragraphs break automatically.
  • Web page addresses and e-mail addresses turn into links automatically.

More information about formatting options

About

Daniel McLaren

Daniel is a Flash and Flex developer specializing in the art of information visualization.

Latest from SketchyD

Latest Drawing from SketchyD

This is the most recent drawing from my mobile sketch blog, SketchyD.com.

Recent comments