Я довольно новичок в 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);
Что вам нужно
<?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(); ?>
Вот как обратный вызов выглядит в 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 вам понадобятся следующие функции:
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>
Вам может быть интересен еще один пример кода
Чтобы использовать обратный вызов внутри класса, вы должны сделать это следующим образом:
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); }