/
Failure, when downloading large files

Failure, when downloading large files

In-Portal uses following code to allow user downloading a protected content (e.g. files) from a website:

header('Content-Length: ' . filesize($filename));
header('Content-type: application/octet-stream');
readfile($filename);
exit;

This widely used approach however might fail in case if downloadable file size is larger, then PHP memory limit, e.g. downloading 100MB file with 32MB memory limit.

To solve this problem I recommend using following code:

header('Content-Length: ' . filesize($filename));
header('Content-type: application/octet-stream');
$size = intval(sprintf("%u", filesize($filename)));
$chunk_size = 1 * (1024 * 1024); // how many bytes per chunk

if ( $size > $chunk_size ) {
	$handle = fopen($filename, 'rb');

	while ( !feof($handle) ) {
		$buffer = fread($handle, $chunk_size);
		echo $buffer;
		ob_flush();
		flush();
	}

	fclose($handle);
}
else {
	readfile($filename);
}
 
exit;

Improved code version read and outputs a file using chunks of 1MB in size, which would hardly break any PHP memory limit out there. This method still can be improved by checking of a user has interrupted download in the middle and not sent rest part of the file.

Related Tasks