Sunday, May 1, 2011

serving large file downloads in php

i used to serving download to users in a very simple fashion that is to simply setting headers like

header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Type: $mimetype");
header("Content-Disposition: attachment; filename=\"$filename\"");
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . $filesize);
  and then reading the file and simply outputting it to browser. like
echo readfile($filename);
  but i realized this wont work always, especially for large downloads since this will load the complete file in memory at once. so i looked and had another techniques guaranteeing it. what we need to do is we will split the file and serve it in chunk by chunk.  
define('CHUNK_SIZE', 1024*1024); // Size (in bytes) of chunk

function readfile_chunked($filename, $retbytes = TRUE) {
$buffer = '';
$cnt =0;
// $handle = fopen($filename, 'rb');
$handle = fopen($filename, 'rb');
if ($handle === false) {
return false;
}
while (!feof($handle)) {
$buffer = fread($handle, CHUNK_SIZE);
echo $buffer;
ob_flush();
flush();
if ($retbytes) {
$cnt += strlen($buffer);
}
}
$status = fclose($handle);
if ($retbytes && $status) {
return $cnt; // return num. bytes delivered like readfile() does.
}
return $status;
}
this worked well for me.