Capture Progress From Command Line

2019-08-09 23:06发布

% Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 12.4M 100 12.4M 0 0 4489k 0 0:00:02 0:00:02 --:--:-- 4653k

The above is a CURL output from the command line when download the file. I have captured this using PHP like so, but I am having trouble working out how to use pre_match to extract the percentage done.

$handle = popen('curl -o '.VIDEOPATH.$fileName.'.flv '.$url, 'rb');

while(!feof($handle))
{
    $progress = fread($handle, 8192);
    //I don't even know what I was attempting here
    $pattern = '/(?<Total>[0-9]{1,3}\.[0-9]{1,2})% of (?<Total>.+) at/';
    //divide received by total somehow, then times 100
    if(preg_match_all($pattern, $progress, $matches)){
    fwrite($fh, $matches[0][0]."\r\n");
    }

} 

How can I do this? Please note, I have no idea what I am doing with the above preg_match_all!

Thanks

Update

Thanks to the help of ylebre. I have this so far.

$handle = popen('curl -o '.VIDEOPATH.$fileName.'.flv '.$url.' 2>&1', 'rb');//make sure its saved to videos

while(!feof($handle))
{

    $line = fgets($handle, 4096); // Get a line from the input handle
    echo '<br>Line'.$line.'<br>';
    $line = preg_replace("/s+/", " ", $line); // replace the double spaces with one
    $fields = explode(" ", $line); // split the input on spaces into fields array
    echo '<br>Fields: '.$fields[0];
    fwrite($fh, $fields[0]); // write a part of the fields array to the output file

} 

I get this output to the browser:


Line % Total % Received % Xferd Average Speed Time Time Time Current

Fields: Line Dload Upload Total Spent Left Speed

Fields: Line 0 1340k 0 4014 0 0 27342 0 0:00:50 --:--:-- 0:00:50 27342 41 1340k 41 552k 0 0 849k 0 0:00:01 --:--:-- 0:00:01 1088k 100 1340k 100 1340k 0 0 1445k 0 --:--:-- --:--:-- --:--:-- 1711k

Fields: Line


How do I extract the percentage part only? Maybe CURL can do this by itself - hmm will ask a question on this.

2条回答
来,给爷笑一个
2楼-- · 2019-08-09 23:30

The progress that is showing up is probably updating the information in the same spot, so it will help if you know what you are parsing exactly.

The next step I recommend is taking one line of input, and trying to get the regexp to work on that.

You could also just split the string at the spaces if I'm reading the output correctly. If you start out by replacing all the double spaces into one. After that you can use explode() to get an array with the values, which you can print_r to take a peek what is inside.

This would be something like:

$line = fgets($handle, 4096); // Get a line from the input handle
$line = preg_replace("/s+/", " ", $line); // replace the double spaces with one
$fields = explode(" ", $line); // split the input on spaces into fields array
fwrite($fh, $fields[0]); // write a part of the fields array to the output file

As long as the ordering in the fields remains the same, your resulting array should give you a consistent result.

Hope this helps!

查看更多
何必那么认真
3楼-- · 2019-08-09 23:51

If you have access to PHP 5.3, you can use the CURL_PROGRESSFUNCTION option, which results in a much more elegant solution (no parsing output). Here's an example of how to use it:

function callback($download_size, $downloaded, $upload_size, $uploaded)
{
  $percent=$downloaded/$download_size;
  // Do something with $percent
}

$ch = curl_init('http://www.example.com');

// Turn off the default progress function
curl_setopt($ch, CURLOPT_NOPROGRESS, false);

// Set up the callback
curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, 'callback');

// You'll want to tweak the buffer size.  Too small could affect performance.  Too large and you don't get many progress callbacks.
curl_setopt($ch, CURLOPT_BUFFERSIZE, 128);

$data = curl_exec($ch);
查看更多
登录 后发表回答