Asked  2 Years ago    Answers:  5   Viewed   80 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?

EDIT:

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");
                break;
                case "zip":
                header("Content-type: application/zip");
                break;
                default:
                header("Content-type: application/octet-stream");
                break;
            }
            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;
                ob_flush();
                flush();    //These two flush commands seem to have helped with performance
            }
        }
        else {
            echo "Error opening file";
        }
        fclose($fd);

 Answers

1

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
2

Change you're header from :

header("Content-type:application/octet-stream");

To :

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

Then you can do :

header("Content-Disposition:attachment;filename="$psp"");
//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
 
4

If you reference the fixtures chapter in the PHPUnit documentation, it tells you about setup() and teardown().

PHPUnit supports sharing the setup code. Before a test method is run, a template method called setUp() is invoked. setUp() is where you create the objects against which you will test. Once the test method has finished running, whether it succeeded or failed, another template method called tearDown() is invoked. tearDown() is where you clean up the objects against which you tested.

This is basically a way of bootstrapping your application prior to running the tests in the test class.

class testMyScript
{
    private $myapp = null;

    public function setup()
    {
       $this->myapp = new My_Application;
       $this->myapp->bootstrap();
    }

    public function testIsMyAppInitialized()
    {
       $this->assertNotNull($this->myapp);      
    }
}
Friday, September 16, 2022
 
1
<?php
$file = 'monkey.gif';

if (file_exists($file)) {
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename='.basename($file));
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Pragma: public');
    header('Content-Length: ' . filesize($file));
    ob_clean();
    flush();
    readfile($file);
    exit;
}

?>

As you can see Content type is application/octet-steam meaning file is byte by byte encoded. Also the cache headers are set. Then headers are forcefully sent by ob_clean();flush(); and then the file is read.

The file_exists is there to ensure that given file exists. You should also try not not thrust user input as they could easy write names for your php codes and download EACH file. And with ../ in names of the files, even your documents or system files and so on.

Wednesday, November 23, 2022
4

The first thing you should do is get a tool like Fiddler and visit a YouTube video page. In Fiddler, you will see all of the files that make up that page, including the FLV itself. Now, you know that the video isn't one of the CSS files, nor is it the image files. You can ignore those. Look for a big file. If you look at the URL, it begins with /videoplayback.

Now, once you've found it, figure out how the browser knew to get that file. Do a search through the sessions (Ctrl+F) and look for "videoplayback". You will see a hit on the first page you went to, like http://www.youtube.com/watch?v=123asdf. If you dig through that file, you'll see a DIV tag with the ID of "watch-player". Within that there is a script tag to setup the flash player, and within that are all of the flash parameters. Within those is the URL to the video.

So now you know how to use your tools to figure out how the browser got to it. How do you duplicate this behavior in PHP?

Do a file_get_contents() on the page that references the video. Ignore everything not in that watch-player div. Parse through the code until you find that variable that contains the URL. From there you will probably have to unescape that URL. Once you have it, you can do a file_get_contents() (or some other download method, depending on what you are trying to do) to get the URL. it is that simple. Your HTML parsing code will be the most complex.

Finally, keep in mind what you are about to do may be illegal. Check the EULA.

Tuesday, November 22, 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 :
 

Browse Other Code Languages