I sort of figured you would say that, so I'm now playing with the code from bertoliati. I've included my current version below.
The first function calls the actual download function, further below. I am using the $xfer and $xfered variables for testing, so the returned values at the moment aren't being used for decision making in the program (they are put into a field in a database which I can check to see what it is after each run). If I can't detect the user's Cancel or Pause events, my intention is to compare the size of the file (that needs to be sent) to the number bytes actually sent.
function tep_redirect_download($url) {
if ( (ENABLE_SSL == true) && (getenv('HTTPS') == 'on') )
{
// We are loading an SSL page
if (substr($url, 0, strlen(HTTP_SERVER)) == HTTP_SERVER)
{
// NONSSL url
// Change it to SSL
$url = HTTPS_SERVER . substr($url, strlen(HTTP_SERVER));
}
}
// $xfer = dl_resume($url);
if ( dl_resume($url) == true )
{
$completed = "done";
}
else
{
$completed = "aborted";
}
return $completed;
// return $xfer;
}
////
// Direct download & test for done-abort
function tep_direct_download($url) {
// $xfer = dl_resume($url);
if (! dl_resume($url) )
{
$completed = "aborted";
}
else
{
$completed = "done";
}
return $completed;
// return $xfer;
}
function dl_resume($path) {
$speed_limit = 0;
//First, see if the file exists
if (! is_file($path) )
{
die("<b>404 File not found!</b>");
}
//Gather relevent info about file
$filename = basename($path);
$file_extension = strtolower(substr(strrchr($filename,"."),1));
$size=filesize($path);
if (isset($_SERVER['HTTP_RANGE'])) {
// Support for partial transfers enabled and browser requested a partial transfer
header("HTTP/1.1 206 Partial content\n");
$start = preg_replace(array("/(\040*|)bytes(\040*|)=(\040*|)/","/(\040*|)\-.*$/"),array("",""),$_SERVER['HTTP_RANGE']);
if ($size < $start)
{
header("HTTP/1.1 411 Length Required\n");
echo "Trying to download past the end of the file. You have probably requested the wrong file. Please try again.";
}
$transfer_size = $size - $start;
header("Accept-Ranges: bytes");
header("Content-Range: bytes ".$transfer_size."-".($size-1)."/".$size);
header("Content-Length:".$transfer_size."\n");
}
else
{
header("HTTP/1.1 200 OK\n");
header("Content-Range: bytes 0-".($size-1)."/$size");
header("Content-Length: $size");
}
header("Cache-control: private\n"); // fix for IE to correctly download files
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Pragma: no-cache\n"); // fix for http/1.0
header("Content-Description: File Transfer");
switch( $file_extension )
{
case "mp3": $ctype="audio/mpeg"; break;
case "mpg":$ctype="video/mpeg"; break;
case "avi": $ctype="video/x-msvideo"; break;
case "wmv": $ctype="video/x-ms-wmv";break;
case "wma": $ctype="audio/x-ms-wma";break;
case "msi": $ctype="application/x-chap4.";break;
default: $ctype="application/force-download";
}
header("Content-Type: " .$ctype);
header("Content-Disposition: attachment; filename=".$filename);
header("Content-Transfer-Encoding: binary");
//open the file
$fh = fopen( $path, 'rb' );
//Set file pointer to the right location
if (isset($transfer_size))
{
fseek($fh,$transfer_size);
}
$curr_user_abort = ignore_user_abort();
ignore_user_abort(false);
$xfered = 0;
if ($speed_limit != 0) {
$chunk = $speed_limit * 1024;
// Stream file in chunks
while(!feof($fh) and (connection_status()==0))
{
echo fread($fh, $chunk);
$xfered = $xfered + $chunk;
flush();
sleep(1);
}
}
else
{
// normal speed download
$chunk = 4096;
while(!feof($fh) && (connection_status()==0) )
{
set_time_limit();
echo fread($fh, $chunk);
$xfered = $xfered + $chunk;
flush();
}
}
fclose($fh);
ignore_user_abort($curr_user_status);
return((connection_status()==0) and !connection_aborted());
}
The above code is how I want it to look when I finish.
To try and figure out a way that I can detect Cancel and Pause, I've been passing various variables back to the original caller.
If I actually download the file,
When I return $xfered, it comes back as the file size (as a multiple of 4096).
When I return $size, it comes back as the actual file size.
When I return $transfer_size, it comes back as -1.
When I return $start, it comes back as NULL.
It seems that the while loop (where $chunk = 4096 is) is executed regardless of the user's action.
Even when the user cancels, $xfered (as in above code) is equal to the file size (as a multiple of 4096). This of course doesn't make sense due to the fact that I set $xfered = 0, and if no download takes place, it should stay at 0. I've cleared the cache in Firefox, so I don't think this is related to the cache on my computer.
I have tried using the ignore_user_abort, and connection_aborted functions in various places.
osCommerce has a register_shutdown_function() set. Could this be the problem? If so, how can I over-ride (or temporarily disable) it?
Since I'm very new to PHP, I don't have the necessary understanding of what's going on to be able to debug the code myself. Can someone help?
Cheers,
Nap