Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP readfile() and large files

Tags:

php

apache

When using readfile() -- using PHP on Apache -- is the file immediately read into Apache's output buffer and the PHP script execution completed, or does the PHP script execution wait until the client finishes downloading the file (or the server times out, whichever happens first)?

The longer back-story:

I have a website with lots of large mp3 files (sermons for a local church). Not all files in the audio archive are allowed to be downloaded, so the /sermon/{filename}.mp3 path is rewritten to really execute /sermon.php?filename={filename} and if the file is allowed to be downloaded then the content type is set to "audio/mpeg" and the file streamed out using readfile(). I've been getting complaints (almost exclusively from iPhone users who are streaming the downloads over 3G) that the files don't fully download, or that they cut off after about 10 or 15 minutes. When I switched from streaming out the file with a readfile() to simply redirecting to the file -- header("Location: $file_url"); -- all of the complaints went away (I even checked with a few users who could reliably reproduce the problem on demand previously).

This leads me to suspect that when using readfile() the PHP script engine is in use until the file is fully downloaded but I cannot find any references which confirm or deny this theory. I'll admit I'm more at home in the ASP.NET world and the dotNet equivalent of readfile() pushes the whole file to the IIS output buffer immediately so the ASP.NET execution pipeline can complete independently of the delivery of the file to the end client... is there an equivalent to this behavior with PHP+Apache?

like image 841
Mike C. Avatar asked Aug 02 '12 22:08

Mike C.


People also ask

What is PHP Readfile function?

The readfile() function reads a file and writes it to the output buffer. Tip: You can use a URL as a filename with this function if the fopen wrappers have been enabled in the php. ini file.

What is the error in Readfile ()?

This means that the ReadFile function is not completing properly. On the MSDN, the error code 1 is ERROR_INVALID_FUNCTION and, in this case, it is in regards to the call to ReadFile .


2 Answers

You may still have PHP output buffering active while performing the readfile(). Check that with:

if (ob_get_level()) ob_end_clean();

or

while (ob_get_level()) ob_end_clean();

This way theonly remaining output Buffer should be apache's Output Buffer, see SendBufferSize for apache tweaks.

EDIT

You can also have a look at mod_xsendfile (an SO post on such usage, PHP + apache + x-sendfile), so that you simply tell the web server you have done the security check and that now he can deliver the file.

like image 128
regilero Avatar answered Sep 21 '22 08:09

regilero


Try using stream_copy_to_stream() instead. I find is has fewer problems than readfile().

set_time_limit(0);
$stdout = fopen('php://output', 'w');
$bfname = basename($fname);

header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"$bfname\"");

$filein = fopen($fname, 'r');
stream_copy_to_stream($filein, $stdout);

fclose($filein);
fclose($stdout);
like image 30
Nidesires Avatar answered Sep 20 '22 08:09

Nidesires