views:

1018

answers:

3

I am making use of AJAX on my site and I would like to show users progress of a file that is being downloaded by my server.

The download is done by script that outputs a percentage to the shell. I would like to pass this info back to the user using AJAX. How can I do this?

Thank you for any help and direction.

I hope your solutions do not involve writing to a text file and retrieving that percentage from the text file!! Too much over head I think.

EDIT - More Info

It is a Linux Shell command - Fedora Core 10.

Currently this is how the shell output looks like:

[download]   9.9% of 10.09M at 10.62M/s ETA 00:00

The percentage changes and I wish to capture that and send it back to the user as it changes.

To execute this, I make use of PHPs exec() function.

+3  A: 

Instead of exec, you could use popen. This will give you a handle you use with fread to grab the output your command generates as it happens.

You'll need to parse out the updates it makes to the percentage indicator. Once you have that data, there are a few ways you could get it to a client, e.g. with a "comet" style push, or have an Ajax request poll for updates.

Paul Dixon
Thank you for your great idea Paul. I am having difficulty waiting for the shell command to give me all the output. I only get part of the output since the command overwrites the last line and my condition: while(!feof($handle)) will not capture the rest of the updates. Any suggestions? Thanks
Abs
A: 

I haven't tried this, but I think this approach would work.

You need three pieces:

  1. Have shell script output its stream to netcat connected to a port
  2. Have a php script listening to stream coming from said port for incoming data, updating a record in memcache or some database w/ the percentage finished.
  3. Have your web script periodically make ajax calls, to the server which checks this value in your backend store.
thesmart
A: 

I'm working on a similar problem. I have to parse the output of my video conversion shell script. I use popen and parse the output of the returned resource. At first I used fgets but that didn't recognize the updated values as new lines. So I created a simple function to that takes an optional $arg_delimiter so you can check for other return types like the chr(13) cariage return. The example code is a bit modified and therefor untested because in my case these functions were methods on my parser object.

function get_line ($arg_handle, $arg_delimiter = NULL)
{
  $delimiter = (NULL !== $arg_delimiter) ? $arg_delimiter : chr(10);
  $result    = array();

  while ( ! feof($arg_handle))
  {
    $currentCharacter = fgetc($arg_handle);

    if ($delimiter === $currentCharacter)
    {
      return implode('', $result);
    }

    $result[] = $currentCharacter;
  }

  return implode('', $result);
}

I simply loop over the results from the popen() resource like this:

  $command = '/usr/bin/yourcommand';
  $handle  = popen($command . ' 2>&1', 'r');

  while ( ! feof($handle))
  {
    $line = get_line($handle, chr(13));

    preg_match($yourParserRegex, $line, $data);

    if (count($data) > 0)
    {
      printf("<script type='text/javascript'>\n  //<![CDATA[\n    window.alert('Result: %s');\n  // ]]>\n</script>"
            ,$data[1]
            );
      flush();
    }

  }

Now all you need to do is figure out the comet stuff.

Marijn Huizendveld