PHP Readfile() and Large Files

Big files download through php function readfile not working

Here is the complete solution thanks to the answer of witzawitz:

I needed to use ob_end_flush() and fread();

<?php 
$sysfile = '/var/www/html/myfile';
if(file_exists($sysfile)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="mytitle"');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($sysfile));
ob_clean();
ob_end_flush();
$handle = fopen($sysfile, "rb");
while (!feof($handle)) {
echo fread($handle, 1000);
}
}
?>

Large files failing to download using readfile()

Here is an example:

$filepath = "done/{$time}/{$latest_filename}";
$size = filesize($filepath);
$mimetype = 'application/ipa';

// Turn off buffering
if (ob_get_level()) {
ob_end_clean();
}

$handle = fopen($filepath, 'rb');
if ($handle !== false && $size > 0) {
@flock($handle, LOCK_SH);

$filename = rawurldecode($filepath);
$old_max_execution_time = ini_get('max_execution_time');
$old_cache_limiter = session_cache_limiter();

ini_set('max_execution_time', 0);
session_cache_limiter(false);

header("Cache-Control: public");
header("Content-Description: File Transfer");
header('Content-Type: ' . $mimetype);
header('Content-Transfer-Encoding: binary');
header('Content-disposition: attachment; filename="'. $filename .'"');
// or your variant
// header("Content-Disposition: attachment; filename=" . md5(time()));

header("Content-Length: $size");

$start = 0;
$end = $size - 1;
$chunk = 8 * 1024;

$requested = (float)$end - (float)$start + 1;

while (! $error) {
if ($chunk >= $requested) {
$chunk = (integer)$requested;
}

set_time_limit(0);

while (! feof($handle) && (connection_status() === 0)) {
if (! $buffer = @fread($handle, $chunk)) {
$error = true;
break 2;
}

print($buffer);
flush();
}

@flock($handle, LOCK_UN);
@fclose($handle);

ini_set('max_execution_time', $old_max_execution_time);
session_cache_limiter($old_cache_limiter);
break;
}

if ($error) {
// 500 - Internal server error
exit;
}
} else {
// Can't open file
exit;
}

Reading very large files in PHP

Are you sure that it's fopen that's failing and not your script's timeout setting? The default is usually around 30 seconds or so, and if your file is taking longer than that to read in, it may be tripping that up.

Another thing to consider may be the memory limit on your script - reading the file into an array may trip over this, so check your error log for memory warnings.

If neither of the above are your problem, you might look into using fgets to read the file in line-by-line, processing as you go.

$handle = fopen("/tmp/uploadfile.txt", "r") or die("Couldn't get handle");
if ($handle) {
while (!feof($handle)) {
$buffer = fgets($handle, 4096);
// Process buffer here..
}
fclose($handle);
}

Edit

PHP doesn't seem to throw an error, it just returns false.

Is the path to $rawfile correct relative to where the script is running? Perhaps try setting an absolute path here for the filename.

PHP readfile() and large downloads

Most likely you are hitting the response buffer limit set by your webserver. IIS and FastCGI are known to have 4mb as the default buffer size. I would start your search with looking into the webserver<->PHP SAPI configuration.

How to download large files through PHP script

If you use fopen and fread instead of readfile, that should solve your problem.

There's a solution in the PHP's readfile documentation showing how to use fread to do what you want.



Related Topics



Leave a reply



Submit