Forum Moderators: coopster

Message Too Old, No Replies

site is unresponsive until download is done

         

pixeltierra

9:15 pm on Aug 19, 2008 (gmt 0)

10+ Year Member



Hi folks, I'm stumped on this one, so any input is welcome. Not sure if this is a code issue, a DB issue, or network issue. I've posted the whole class below for reference.

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.";

}
}

eelixduppy

6:06 am on Aug 20, 2008 (gmt 0)



Do you get the same behavior with multiple browsers? My guess is this is an issue with the server itself, and not the script you have written.

pixeltierra

6:49 am on Aug 20, 2008 (gmt 0)

10+ Year Member



The tests I've done show that this happens in all browsers and OSs.

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?

phranque

8:19 am on Aug 20, 2008 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



perhaps you are limited in the number of concurrent connections to the server.
i know you can easily check these values in ff.
this thread may give you some hints to look for:
[webmasterworld.com...]

pixeltierra

5:15 pm on Aug 20, 2008 (gmt 0)

10+ Year Member



I have looked at the about:config in FF and it allows 8 connections.

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.