admin管理员组文章数量:1287125
I can't figure out how to push the progress out every time it updates using php. For the sake of clarity, I will write an example.
jQuery:
function uploadMovieDownload(link){
$.post("php/downloadmovie.php", { source:link }, function(json){ console.log(json); });
}
uploadMovieDownload(url);
PHP (php/downloadmovie.php):
session_start();
ob_start();
date_default_timezone_set("Europe/Bucharest");
ini_set('display_errors',true);
require_once(dirname(__FILE__)."/functions.php");
$url = $_POST['source'];
$headers = getHeaders($url);
$url = $headers['url'];
$path = dirname(__FILE__)."/temp/test.mp4";
$fp = fopen ($path, 'w+');
$ch = curl_init();
curl_setopt( $ch, CURLOPT_URL, $url );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, false );
curl_setopt( $ch, CURLOPT_PROGRESSFUNCTION, 'progress' );
curl_setopt( $ch, CURLOPT_NOPROGRESS, false );
curl_setopt( $ch, CURLOPT_BINARYTRANSFER, true );
curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false );
curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, 100 );
curl_setopt( $ch, CURLOPT_FILE, $fp );
curl_exec( $ch );
curl_close( $ch );
fclose( $fp );
function progress($resource,$download_size, $downloaded, $upload_size, $uploaded){
if($download_size > 0) echo $downloaded / $download_size * 100;
ob_flush();
flush();
}
echo "Done";
ob_flush();
flush();
The problem I have is that it returns the progress after it pletes, it isn't pushing it while downloading. Thanks in advance if you have any sugestions.
I can't figure out how to push the progress out every time it updates using php. For the sake of clarity, I will write an example.
jQuery:
function uploadMovieDownload(link){
$.post("php/downloadmovie.php", { source:link }, function(json){ console.log(json); });
}
uploadMovieDownload(url);
PHP (php/downloadmovie.php):
session_start();
ob_start();
date_default_timezone_set("Europe/Bucharest");
ini_set('display_errors',true);
require_once(dirname(__FILE__)."/functions.php");
$url = $_POST['source'];
$headers = getHeaders($url);
$url = $headers['url'];
$path = dirname(__FILE__)."/temp/test.mp4";
$fp = fopen ($path, 'w+');
$ch = curl_init();
curl_setopt( $ch, CURLOPT_URL, $url );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, false );
curl_setopt( $ch, CURLOPT_PROGRESSFUNCTION, 'progress' );
curl_setopt( $ch, CURLOPT_NOPROGRESS, false );
curl_setopt( $ch, CURLOPT_BINARYTRANSFER, true );
curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false );
curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, 100 );
curl_setopt( $ch, CURLOPT_FILE, $fp );
curl_exec( $ch );
curl_close( $ch );
fclose( $fp );
function progress($resource,$download_size, $downloaded, $upload_size, $uploaded){
if($download_size > 0) echo $downloaded / $download_size * 100;
ob_flush();
flush();
}
echo "Done";
ob_flush();
flush();
The problem I have is that it returns the progress after it pletes, it isn't pushing it while downloading. Thanks in advance if you have any sugestions.
Share Improve this question edited Dec 31, 2016 at 21:42 LF-DevJourney 28.6k30 gold badges165 silver badges316 bronze badges asked Jan 30, 2015 at 17:10 d3nm4kd3nm4k 1,0231 gold badge8 silver badges12 bronze badges 2- Hi have you got the solution for this issue.... – Ashish Commented Dec 30, 2016 at 13:02
-
a few ideas: 1. load balancers can inadvertently save up gradual responses. 2. you need to ship a certain # of bytes right away to get some browsers to behave right. 3. you need to return HTML with the data methodically wrapped in
<script>
tags to use a simplistic COMET approach like this. 4. i would consider re-implementing using a temp file to store the percentage and pinging another simple script to fetch that value from the file, bypassing the above script. 5. "SSE", akaEventSource
is cross-browser and easy to implement in PHP to replace the pinging in #4... – dandavis Commented Dec 30, 2016 at 21:42
4 Answers
Reset to default 11 +50with that method, you'll run in to all kind of caching problems, is php output buffering? you'll have a problem. are you behind a web server, ala nginx/apache/lighthttp/anything? you'll have a problem. is the browser cacheing output? (all mainstream browsers do), you'll have a problem.
i suggest an alternative which will have none of those problems: using $_SESSION to store download percentage, and querying the percentage with XMLHttpRequests (actually querying the percentage over WebSockets would be optimal, lagless, use less bw, etc, but much harder to implement)
downloadmovie.php
<?php
require_once(dirname(__FILE__)."/functions.php");
$url = $_POST['source'];
$headers = getHeaders($url);
$url = $headers['url'];
//after validation of input
session_start();
$_SESSION['download_percentage']=0.0;//initialize it
session_write_close();
fastcgi_finish_request();//or if you're not using fcgi, some equivalent..
$path = dirname(__FILE__)."/temp/test.mp4";
$fp = fopen ($path, 'w+');
$ch = curl_init();
curl_setopt( $ch, CURLOPT_URL, $url );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, false );
curl_setopt( $ch, CURLOPT_PROGRESSFUNCTION, 'progress' );
curl_setopt( $ch, CURLOPT_NOPROGRESS, false );
curl_setopt( $ch, CURLOPT_BINARYTRANSFER, true );
curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false );
curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, 100 );
curl_setopt( $ch, CURLOPT_FILE, $fp );
curl_exec( $ch );
curl_close( $ch );
fclose( $fp );
function progress($resource,$download_size, $downloaded, $upload_size, $uploaded){
$percentage=$download_size==0? 0.0 : (($downloaded/$download_size)*100);
session_start();
$_SESSION['download_percentage']=$percentage;
session_write_close();
}
getProgress.xhr.php
<?php
if(""===session_id()){
session_start();
}
echo $_SESSION['download_percentage']??'?';
then monitoring the progress in the browser:
(function checkProgress() {
"use strict";
var xhr = new XMLHttpRequest();
xhr.open("GET", "getProgress.xhr.php");
xhr.addEventListener("readystatechange", function(ev) {
var xhr = ev.target;
if (xhr.readyState !== 4) {
return;
}
console.log(xhr.responseText + " percent downloaded!");
if (xhr.responseText === "100") {
return; /*stop checking for progress when its finished*/
}
setTimeout(checkProgress, 1000); //<<check for progress every 1 second
});
xhr.send();
})();
important edit: as @drew010 pointed out, it won't work without session_write_close();session_start(); each time curl updates the value, fixed that.
Quote from cURL download progress in PHP
echo "<pre>";
echo "Loading ...";
ob_flush();
flush();
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://stackoverflow.");
//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();
?>
Don't use ob_flush(), just flush(). (Remove all the ob_ functions). Also, consider modifying the buffersize:
curl_setopt($ch, CURLOPT_BUFFERSIZE, 16000);
Experiment with the size.
PHP will show the results when all the scripts are done. This is the reason that you just the finish progress.
You can execute the curl downloading in the background, and write the progress to session, database, session or memory such as redis, memchche. Then in the client side read the process every very short time.
You also can use Iframe to do this.
本文标签: javascriptPHP cURL download progress using jqueryStack Overflow
版权声明:本文标题:javascript - PHP cURL download progress using jquery - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741262735a2367919.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论