Viewed   86 times

Using PHP, I am trying to serve large files (up to possibly 200MB) which aren't in a web accessible directory due to authorization issues. Currently, I use a readfile() call along with some headers to serve the file, but it seems that PHP is loading it into memory before sending it. I intend to deploy on a shared hosting server, which won't allow me to use much memory or add my own Apache modules such as X-Sendfile.

I can't let my files be in a web accessible directory for security reasons. Does anybody know a method that is less memory intensive which I could deploy on a shared hosting server?


if(/* My authorization here */) {
        $path = "/uploads/";
        $name = $row[0];           //This is a MySQL reference with the filename
        $fullname = $path . $name; //Create filename
        $fd = fopen($fullname, "rb");
        if ($fd) {
            $fsize = filesize($fullname);
            $path_parts = pathinfo($fullname);
            $ext = strtolower($path_parts["extension"]);
            switch ($ext) {
                case "pdf":
                header("Content-type: application/pdf");
                case "zip":
                header("Content-type: application/zip");
                header("Content-type: application/octet-stream");
            header("Content-Disposition: attachment; filename="".$path_parts["basename"].""");
            header("Content-length: $fsize");
            header("Cache-control: private"); //use this to open files directly
            while(!feof($fd)) {
                $buffer = fread($fd, 1*(1024*1024));
                echo $buffer;
                flush();    //These two flush commands seem to have helped with performance
        else {
            echo "Error opening file";



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.

Monday, November 14, 2022

Send a content-disposition attachment header.

Monday, December 19, 2022

Change you're header from :


To :

header("Content-type: video/flv");

Then you can do :

//allways a good idea to let the browser know how much data to expect
header("Content-length: " . filesize($psp) . "nn"); 
echo file_get_contents($psp); //$psp should contain the full path to the video
Sunday, November 13, 2022

This is pretty easy. All you need to do is provide cURL with a callback to handle data as it comes in.

function onResponseBodyData($ch, $data)
    echo $data;
    return strlen($data);

curl_setopt($ch, CURLOPT_WRITEFUNCTION, 'onResponseBodyData');

Returning the length of data from your callback is important. It signifies how much data you processed. If you return something other than the length of data passed in (such as 0), then the request is aborted.

Now, make sure you don't have output buffering turned on, and configure your server to not buffer the entire response before sending. It will work out of the box on most configurations.

You can find more examples here:

Saturday, December 10, 2022

Yes, you can combine XmlReader with the method XNode.ReadFrom, see the example in the documentation which uses C# to selectively process nodes found by the XmlReader as an XElement.

Sunday, September 25, 2022
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :