Download fails on files greater than 10M
03-04-2008, 03:18 PM
|
Download fails on files greater than 10M
|
Posts: 199
|
Using the following code, files greater than 10Megs do not download. Less than 10 is working. Can anyone explain why? Files that will be downloaded are 5G plus in size.
Code:
function download() {
global $_GET;
//Gather relevent info about file
$file = "/user/dac420/tts/incoming/".$_GET['name'];
$len = filesize($file);
$filename = basename($file);
$file_extension = strtolower(substr(strrchr($filename,"."),1));
// Determine correct MIME type
switch($file_extension){
case "asf": $ctype = "video/x-ms-asf"; break;
case "avi": $ctype = "video/x-msvideo"; break;
case "exe": $ctype = "application/octet-stream"; break;
case "mov": $ctype = "video/quicktime"; break;
case "mp3": $ctype = "audio/mpeg"; break;
case "mpg": $ctype = "video/mpeg"; break;
case "mpeg": $ctype = "video/mpeg"; break;
case "rar": $ctype = "encoding/x-compress"; break;
case "txt": $ctype = "text/plain"; break;
case "wav": $ctype = "audio/wav"; break;
case "wma": $ctype = "audio/x-ms-wma"; break;
case "wmv": $ctype = "video/x-ms-wmv"; break;
case "zip": $ctype = "application/x-zip-compressed"; break;
default: $ctype = "application/force-download"; break;
}
//Begin writing headers
header("Cache-Control:");
header("Cache-Control: public");
//Use the switch-generated Content-Type
header("Content-Type: $ctype");
if (strstr($_SERVER['HTTP_USER_AGENT'], "MSIE")) {
# workaround for IE filename bug with multiple periods / multiple dots in filename
# that adds square brackets to filename - eg. setup.abc.exe becomes setup[1].abc.exe
$iefilename = preg_replace('/\./', '%2e', $filename, substr_count($filename, '.') - 1);
header("Content-Disposition: attachment; filename=\"$iefilename\"");
} else {
header("Content-Disposition: attachment; filename=\"$filename\"");
}
header("Accept-Ranges: bytes");
$size=filesize($file);
//check if http_range is sent by browser (or download manager)
if(isset($_SERVER['HTTP_RANGE'])) {
list($a, $range)=explode("=",$_SERVER['HTTP_RANGE']);
//if yes, download missing part
str_replace($range, "-", $range);
$size2=$size-1;
$new_length=$size2-$range;
header("HTTP/1.1 206 Partial Content");
header("Content-Length: $new_length");
header("Content-Range: bytes $range$size2/$size");
} else {
$size2=$size-1;
header("Content-Range: bytes 0-$size2/$size");
header("Content-Length: ".$size);
}
//open the file
$fp=fopen("$file","rb");
//seek to start of missing part
fseek($fp,$range);
//start buffered download
while(!feof($fp)){
//reset time limit for big files
set_time_limit(0);
print(fread($fp,filesize($file)));
flush();
ob_flush();
}
fclose($fp);
exit;
}
|
|
|
|
03-04-2008, 04:01 PM
|
Re: Download fails on files greater than 10M
|
Posts: 3,621
Name: Thierry
Location: I'm the uber Spaminator !
|
What error do you have ?
__________________
Only a biker knows why a dog sticks his head out the window.
|
|
|
|
03-04-2008, 04:09 PM
|
Re: Download fails on files greater than 10M
|
Posts: 199
|
PHP Fatal error: Allowed memory size of 8388608
bytes exhausted (tried to allocate 11076561 bytes)
|
|
|
|
03-04-2008, 04:39 PM
|
Re: Download fails on files greater than 10M
|
Posts: 3,621
Name: Thierry
Location: I'm the uber Spaminator !
|
What I thought....
If your file is binary, there are many chances that the datas are stored on 1 big line.
You use fread, good. But you need to specify a "read up to" value below your max_memory threshold.
Right now, you ask it to get the whole file content in 1 operation.
PHP Code:
fread($fp,filesize($file))
You will need to split the processing in several parts.
Look at that comment for an example.
It should resolve your case.
PHP Code:
$total = filesize($file); $sent = 0; $blocksize = (2 << 20); //2M chunks $handle = fopen($file, "r");
while($sent < $total){ echo fread($handle, $blocksize); $sent += $blocksize; } exit(0);
And for those (like me) that didn't knew about the << operator, it's a "bitwise shift left".
http://www.php.net/manual/en/languag...rs.bitwise.php
Now, I need to understand what it does.....
Edit:
Ok, now, Wikipedia was really useful to understand it better. If any of you is interested:
http://en.wikipedia.org/wiki/Bitwise_operation
__________________
Only a biker knows why a dog sticks his head out the window.
Last edited by tripy; 03-04-2008 at 04:58 PM..
|
|
|
|
03-04-2008, 05:33 PM
|
Re: Download fails on files greater than 10M
|
Posts: 2,918
Name: Keith Marshall
Location: Connecticut
|
These two lines might help in your htaccess file:
Code:
php_value post_max_size 110M
php_value upload_max_filesize 100M
__________________
<mgraphic /> - I don't have a solution but I admire the problem.
|
|
|
|
03-04-2008, 05:45 PM
|
Re: Download fails on files greater than 10M
|
Posts: 3,621
Name: Thierry
Location: I'm the uber Spaminator !
|
Quote:
Originally Posted by mgraphic
These two lines might help in your htaccess file:
Code:
php_value post_max_size 110M
php_value upload_max_filesize 100M
|
Nope, they will not.
He sends a file for download, he's not receiving an upload.
He should alter the max_memory value if he would to achieve this without modifying the script, but he might hit the wall again the day a file definitively bigger than the max_memory will be downloaded.
It can go up to crashing the server because all it's memory would be dispatched to the script.
That's why I explained why to fix it rather than how raising the max_memory limit.
__________________
Only a biker knows why a dog sticks his head out the window.
|
|
|
|
03-05-2008, 12:57 AM
|
Re: Download fails on files greater than 10M
|
Posts: 1,226
Name: Mike
Location: Mataro, Spain
|
Wtf. You never should send files through php fread(). Install some lightweight webserver like nginx or lighttpd to send large static files with conditions check.
|
|
|
|
03-05-2008, 04:30 AM
|
Re: Download fails on files greater than 10M
|
Posts: 199
|
Thanks Trippy, your solution worked.
Now it seem my fseek() is failing... actually $_SERVER['HTTP_RANGE'] is never being set. How do i get this to set?
|
|
|
|
03-05-2008, 04:44 AM
|
Re: Download fails on files greater than 10M
|
Posts: 3,621
Name: Thierry
Location: I'm the uber Spaminator !
|
Quote:
|
actually $_SERVER['HTTP_RANGE'] is never being set. How do i get this to set?
|
For that, I have no idea. Sorry.
PHP Code:
//seek to start of missing part fseek($fp,$range);
it's because you don't set any $range value in your else.
Set it to 0 (I guess) and try again.
__________________
Only a biker knows why a dog sticks his head out the window.
|
|
|
|
03-10-2008, 12:57 AM
|
Re: Download fails on files greater than 10M
|
Posts: 199
|
So now that I have the download working I need to know why the page is not refreshing at the end of the script. The download happen, then nothing. How do i get the page to continue after download?
|
|
|
|
03-10-2008, 07:31 AM
|
Re: Download fails on files greater than 10M
|
Posts: 3,621
Name: Thierry
Location: I'm the uber Spaminator !
|
hmm, don't know, as we don't see your page code.
But, did you tried to redirect after the end of the download() function ?
PHP Code:
header("location: /sompage.html"); die();
__________________
Only a biker knows why a dog sticks his head out the window.
|
|
|
|
03-11-2008, 04:06 AM
|
Re: Download fails on files greater than 10M
|
Posts: 199
|
This is my function so far. I still haven't gotten the header() at the end to work, or the resume on fail feature. Still working on it.
PHP Code:
function download() {
global $_GET,$_SERVER;
require '../db/db.inc'; $connection = mysql_connect($hostname,$username,$password); if (!($connection)) die ("can not connect"); mysql_select_db($databasename,$connection);
/* update download count for file. update who downloaded - 3/1/2008 */ $query_update = "UPDATE datalog SET timesdownloaded = timesdownloaded + 1 WHERE dataid = '".$_GET['id']."'"; mysql_query($query_update,$connection);
/* update download count for file. update who downloaded - 3/1/2008 */ $query_update = "INSERT INTO download_log (universalid,dataid,status) VALUES ('".$_SERVER['HTTP_SM_UNIVERSALID']."','".$_GET['id']."','1')"; mysql_query($query_update,$connection);
//Gather relevent info about file $file = "/user/dac420/tts/incoming/".$_GET['name']; $len = filesize($file); $filename = basename($file); $file_extension = strtolower(substr(strrchr($filename,"."),1));
// Determine correct MIME type switch($file_extension){
case "asf": $ctype = "video/x-ms-asf"; break; case "avi": $ctype = "video/x-msvideo"; break; case "exe": $ctype = "application/octet-stream"; break; case "mov": $ctype = "video/quicktime"; break; case "mp3": $ctype = "audio/mpeg"; break; case "mpg": $ctype = "video/mpeg"; break; case "mpeg": $ctype = "video/mpeg"; break; case "rar": $ctype = "encoding/x-compress"; break; case "txt": $ctype = "text/plain"; break; case "wav": $ctype = "audio/wav"; break; case "wma": $ctype = "audio/x-ms-wma"; break; case "wmv": $ctype = "video/x-ms-wmv"; break; case "zip": $ctype = "application/x-zip-compressed"; break; default: $ctype = "application/force-download"; break;
}
//Begin writing headers header("Cache-Control:"); header("Cache-Control: public");
//Use the switch-generated Content-Type header("Content-Type: $ctype");
if (strstr($_SERVER['HTTP_USER_AGENT'], "MSIE")) { # workaround for IE filename bug with multiple periods / multiple dots in filename # that adds square brackets to filename - eg. setup.abc.exe becomes setup[1].abc.exe $iefilename = preg_replace('/\./', '%2e', $filename, substr_count($filename, '.') - 1); header("Content-Disposition: attachment; filename=\"$iefilename\""); } else { header("Content-Disposition: attachment; filename=\"$filename\""); }
header("Accept-Ranges: bytes");
$size=filesize($file);
//check if http_range is sent by browser (or download manager) if(isset($_SERVER['HTTP_RANGE'])) {
list($a, $range)=explode("=",$_SERVER['HTTP_RANGE']);
//if yes, download missing part str_replace($range, "-", $range); $size2=$size-1; $new_length=$size2-$range;
header("HTTP/1.1 206 Partial Content"); header("Content-Length: $new_length"); header("Content-Range: bytes $range$size2/$size");
} else {
$size2=$size-1; header("Content-Range: bytes 0-$size2/$size"); header("Content-Length: ".$size);
}
//open the file $fp=fopen($file,"rb");
//seek to start of missing part fseek($fp,$range);
//reset time limit for big files set_time_limit(0);
//start buffered download while(!feof($fp)){
$total = filesize($file); $sent = 0; $blocksize = (2 << 20); //2M chunks $handle = fopen($file, "r");
// Now we need to loop through the file and echo out chunks of file data // Dumping the whole file fails at > 30M! while($sent < $total){ echo fread($handle, $blocksize); $sent += $blocksize; }
@flush(); @ob_flush(); }
fclose($fp);
header("location: /welcome.php");
}
Last edited by empiresolutions; 03-11-2008 at 04:08 AM..
|
|
|
|
03-13-2008, 09:06 AM
|
Re: Download fails on files greater than 10M
|
Posts: 340
Name: Jon
Location: New York
|
the header wont work if there is out put to the browser before it. so if there is no output it will work
__________________
AMW_Drizz
Dev Machine:: Apache 2.2.6 PHP 5.2.6 MySQL 5.1
|
|
|
|
|
« Reply to Download fails on files greater than 10M
|
|
|
| Thread Tools |
Search this Thread |
|
|
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
|