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 completes, it isn't pushing it while downloading. Thanks in advance if you have any sugestions.
with 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With