Forum Moderators: coopster
I wrote the class to control a force video download. The class works fine, but during download (can take 5-10 minutes) the site is unresponsive until the download is finished.
The setup is this: there is a link like this <a href='download.php?infofordownload'>download</a> on my_page.php
When you click the link, my_page.php stays loaded in the browser, because the download.php page has the header of a video file. The browser askes what to do with it, and you save it. Fine and good. But why would the site not respond while a download is in progress? Site responds to other site user, just not the user who is downloading...
Any help appreciated.
class forceDownload {
//for a good start on this concept, see the user notes on php.net for "readfile()"var $msg; //explains why start() succeeds or fails
var $file;
var $clip_id;
var $type;
var $filesize;
var $download_id;//id of record started in downloads table for this download (unix timestamp). Needed for finalize_download_record()
var $download_name;
function start( $file,
$filename,//file name diplayed on OS download window
$clip_id,
$type,
$ct = "video/mpeg4" //content type
)
{
global $db;
//check that file exists
if (!file_exists($file)) {
$this->msg = "Download error: File $file does not exist on the server.";
return FALSE;
}
//set up vars
if (!$filename) $filename = basename($file); //set default as filesystem name
$mode= 'rb';//read binary
$chunksize= 4096;//size of chunk that file is read and output
$bytes_sent= 0;
$bytes_total= filesize($file);
$this->file= $file;
$this->clip_id= $clip_id;
$this->type= $type;
$this->filesize= $bytes_total;
$this->download_id = time();//see var defs above
$this->download_name= $filename;//see var defs above
//set script execution time to something long so big downloads don't timeout. Default is 30secs
ini_set('max_execution_time', 15 * 60);
//open file
$handle= fopen($file, $mode);
//abort if can't open file
if (!$handle) {
$this->msg = "Download error: Couldn't open file $file in mode '$mode'";
return FALSE;
}
// start record of this download
$this->start_download_record();
// send the right headers
header("Cache-Control: private");
header("Content-Type: $ct");
header("Content-Disposition: attachment; filename=\"$filename\"");
header("Content-Length: " . filesize($file));
header("Connection: close");
// dump the file, keeping track of how much has been downloaded.
while(!feof($handle)) {
set_time_limit(15 * 60);
$buf = fread($handle, $chunksize);
echo $buf;
flush();
$bytes_sent+=strlen($buf); /* We know how many bytes were sent to the user */
//store percent downloaded (keeps mysql connection alive)
$r2 = $db->update('downloads', array('percent_downloaded' => round(100 * $bytes_sent / $bytes_total)), "download_id = $this->download_id");
//pear_error_check($r2);
}
fclose($handle);
if ($bytes_sent==$bytes_total) {
$this->msg = "Download success: $bytes_sent bytes sent of $bytes_total.";
return TRUE;
} else {
$this->msg = "Download error: File $file was not completely sent.";
return FALSE;
}
}
//stores initial info about attempted download,
//if finalize_download_record below is never called, then this download is recorded as incomplete
function start_download_record () {
global $db;
//make initial entry in downloads table, setting success to 0
$vals = array(
'download_id' => $this->download_id,
'username' => $_SESSION['username'],
'date' => MYSQL_NOW,
'file'=> $this->file,
'clip_id'=> $this->clip_id,
'type'=> $this->type,
'filesize'=> $this->filesize,
'download_name'=> $this->download_name,
);
$r = $db->insert('downloads', $vals);
pear_error_check($r);
$this->msg .= "Download record started.";
}
}
To be more clear, once the download starts, the site will not respond to that user in that browser until the download is finished. This is the case even if the download is started in its own tab or own window. However, to some other user in the world, the site responds fine (so not a cpu thing), and also if I download in IE, the site responds fine in FF during the download in IE (so not an IP thing?).
So is this a browser issue? I don't know what to do to make this work. Please help.
The only thing I can think of is that the server will only take one page request from the browser at once maybe?
Some more info I've found is this: I've installed live HTTP headers, and have noted that when I make a second page request while the file is downloading, no headers are sent to the server. Then if I wait long enough (haven't timed it) the browser comes up with a dialog box that says "you have chosen to download the_file.php", and asks to save or choose program. If I save to disk, the file is empty, if I choose FF as the ap to open, I get the same dialog again.
This is the last hump for a site that is to be launched this week if possible, so please, any help is very appreciated.