Прогресс загрузки cURL в PHP - программирование
Подтвердить что ты не робот

Прогресс загрузки cURL в PHP

Я новичок в 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); 
4b9b3361

Ответ 1

Вам нужно

<?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();

?>

Ответ 2

Вот как обратный вызов выглядит в C:

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

Вероятно, в PHP он должен выглядеть как

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

Итак, если у вас есть page.html, который загружает .php файл в iframe.

В вашем php script вам понадобятся следующие функции:

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

который должен производить вывод, аналогичный следующему:

0
0.1
0.2
0.2
0.3
0.4
...

то на странице iframe у вас будет индикатор выполнения

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

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%;
}

javascript

var progressElement = document.getElementById('progress')

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

Вы можете загрузить его на JavaScript и обновить индикатор выполнения, например:

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

Вам может быть интересен еще примерный код

Ответ 3

Чтобы использовать обратный вызов внутри класса, вы должны сделать это следующим образом:

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

или при использовании статических функций, например:

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

... для функции обратного вызова, чтобы сделать все, что вам нужно:

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);
}