php PHP中的cURL下载进度

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13958303/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 06:21:20  来源:igfitidea点击:

cURL download progress in PHP

phpcurl

提问by Martin

I'm pretty new to cURL so I've been struggling with this one for hours. I'm trying to download the source of a website in an iframe using cURL and while it's loading to show how much of it is loaded. So far I have successfully downloaded the source without showing the loading progress. Can you explain how to show the download progress? Without cURL I would read the file byte by byte and divide the total amount of downloaded bytes with the total size of the file. How can this be done in cURL since it reads the source as a whole? (at least I think that this is the only way, not sure) Here's what I've got so far:

我对 cURL 很陌生,所以我一直在为这个问题苦苦挣扎了几个小时。我正在尝试使用 cURL 在 iframe 中下载网站的源代码,并在加载时显示加载了多少。到目前为止,我已经成功下载了源代码,而没有显示加载进度。你能解释一下如何显示下载进度吗?如果没有 cURL,我会逐字节读取文件并将下载的字节总数除以文件的总大小。由于 cURL 将源作为一个整体读取,因此如何在 cURL 中完成此操作?(至少我认为这是唯一的方法,不确定)这是我到目前为止所得到的:

/* Download source */
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $adress);  
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, 0); 
curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
$html = curl_exec($ch);
curl_close($ch); 

回答by Baba

What you need is

你需要的是

<?php
ob_start();

echo "<pre>";
echo "Loading ...";

ob_flush();
flush();

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://stackoverflow.com");
//curl_setopt($ch, CURLOPT_BUFFERSIZE,128);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, 'progress');
curl_setopt($ch, CURLOPT_NOPROGRESS, false); // needed to make progress function work
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
$html = curl_exec($ch);
curl_close($ch);


function progress($resource,$download_size, $downloaded, $upload_size, $uploaded)
{
    if($download_size > 0)
         echo $downloaded / $download_size  * 100;
    ob_flush();
    flush();
    sleep(1); // just to see effect
}

echo "Done";
ob_flush();
flush();

?>

回答by Kush

This is how the callback looks in C:

这是回调在 C 中的样子:

typedef int (*curl_progress_callback)(void *clientp,
                                      double dltotal,
                                      double dlnow,
                                      double ultotal,
                                      double ulnow);

Probably in PHP it should look like

可能在 PHP 中它应该看起来像

curl_progress_callback($clientp, $dltotal, $dlnow, $ultotal, $ulnow)

So, assuming you have page.html which loads a .php file in an iframe.

因此,假设您有 page.html 在 iframe 中加载 .php 文件。

In your php script, you will require the following functions:

在您的 php 脚本中,您将需要以下功能:

curl_setopt($curl, CURLOPT_PROGRESSFUNCTION, 'curl_progress_callback');    
curl_setopt($curl, CURLOPT_BUFFERSIZE,64000);    
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);

which should produce an output similar to the following:

这应该产生类似于以下内容的输出:

0
0.1
0.2
0.2
0.3
0.4
...

then on the iframe page, you will have a progress bar

然后在 iframe 页面上,您将有一个进度条

<div id="progress-bar">
    <div id="progress">0%</div>
</div>

CSS would be something like this

CSS 应该是这样的

#progress-bar {
    width: 200px;
    padding: 2px;
    border: 2px solid #aaa;
    background: #fff;
}

#progress {
    background: #000;
    color: #fff;
    overflow: hidden;
    white-space: nowrap;
    padding: 5px 0;
    text-indent: 5px;
    width: 0%;
}

The javascript

javascript

var progressElement = document.getElementById('progress')

function updateProgress(percentage) {
    progressElement.style.width = percentage + '%';
    progressElement.innerHTML = percentage + '%';
}

You can have it output JavaScript and have it update the progress bar for you, for example:

你可以让它输出 JavaScript 并让它为你更新进度条,例如:

<script>updateProgress(0);</script>
<script>updateProgress(0.1);</script>
<script>updateProgress(0.2);</script>

You might be interested in some more example code

您可能对更多示例代码感兴趣

回答by STWilson

To use the callback inside a class, you must do it like this:

要在类中使用回调,您必须这样做:

curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, array($this, 'progress'));

or if using static functions, like this:

或者如果使用静态函数,像这样:

curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, array('self', 'progress'));

... to a callback function to do whatever you need:

...到回调函数来做你需要的任何事情:

private static function progress($resource, $downloadSize, $downloaded, $uploadSize, $uploaded)
{
    // emit the progress
    Cache::put('download_status', [
        'resource' => $resource,
        'download_size' => $downloadSize,
        'downloaded' => $downloaded,
        'upload_size' => $uploadSize,
        'uploaded' => $uploaded
    ], 10);
}