Die readfile(), die!

Die readfile(), die!

by Martín Langhoff -
Number of replies: 6
I just discovered we are using readfile() in a few places in the code. Readfile is now being affected by a bug in some PHP5 versions -- this has been discussed in other threads -- where readfile serves only the first 2MB and then gives up.

Even when it works correctly, it loads the whole file into memory. So you are bound by PHP's memory limits in the filesizes you can server, and PHP doesn't release memory, messing up your memory management. Argh.

A better replacement for readfile looks roughly like:

function readfile_chunked($filename,$retbytes=true) {
$chunksize = 1*(1024*1024); // how many bytes per chunk
$buffer = '';
$cnt =0;
// $handle = fopen($filename, 'rb');
$handle = fopen($filename, 'rb');
if ($handle === false) {
return false;
}
while (!feof($handle)) {
$buffer = fread($handle, $chunksize);
echo $buffer;
if ($retbytes) {
$cnt += strlen($buffer);
}
}
$status = fclose($handle);
if ($retbytes && $status) {
return $cnt; // return num. bytes delivered like readfile() does.
}
return $status;

}

I am mostly concerned about send_file() in lib/filelib.php -- we'll be testing this replacement today.
Average of ratings: -
In reply to Martín Langhoff

Re: Die readfile(), die!

by Martin Dougiamas -
Picture of Core developers Picture of Documentation writers Picture of Moodle HQ Picture of Particularly helpful Moodlers Picture of Plugin developers Picture of Testers
Big problem, and thanks for attending to it.

It has to work 100%, obviously ... smile
In reply to Martin Dougiamas

Re: Die readfile(), die!

by Adam Fleischmann -

Hello,

i have the same problem: filedownload stops at ca. 1.8mb.

i read, it is a bug of php5;

is there a solution for this problem?

thanks

adam

In reply to Martín Langhoff

Re: Die readfile(), die!

by Robert Brenstein -
Please let us know how the tests came out and what the final code is, so we can patch our 1.4.x installations. The short patch posted elsewhere seems to be working fine but this seems more robust.

I also think that info about this issue with PHP5 and the link to patch should be in front page accouncements, so people do not keep discovering it the hard way.

A potential side benefit of this new function is that moodle can allow setting chunk size for downloads which can allow us finer tuning of our network performance (by making the chunk size a parameter definable in the site settings).
In reply to Robert Brenstein

Re: Die readfile(), die!

by Martin Dougiamas -
Picture of Core developers Picture of Documentation writers Picture of Moodle HQ Picture of Particularly helpful Moodlers Picture of Plugin developers Picture of Testers
Has anyone been using this patch and got any results to report?
In reply to Martin Dougiamas

Re: Die readfile(), die!

by Mike Churchward -
Picture of Core developers Picture of Plugin developers Picture of Testers
One of my clients ran into this problem this week. They just upgraded to V5. Now they can't get any files over 2Mb.

I'm going to implement this code and see what happens.

mike
In reply to Mike Churchward

Re: Die readfile(), die!

by Adam Fleischmann -

We had the same problem on our machines with files bigger than 2mb.

i upgraded php5 with the latest cvs version, and now filedownload bigger than 2mb works fine.

adam