Ashley Sheridan​.co.uk

Streaming Files for Security

Posted on

Picture the scenario: You've just set up a social networking site for your niche hobby of collecting old tin cans. Part of the site is an image gallery that allows members to upload pictures of their collections. You want to make sure that only members can see these images, but how?

Preventing access to a page that contains the image is easy, but what if they try to link to the image directly? One way is to have a PHP script stream the file to the browser.

The below script will open the file and stream it put, as if it were the actual file itself.

<?php $file = 'images/test.jpg'; $filename = '"' . basename($file) . '"'; header("Content-Disposition: attachment; filename=$filename"); header("Content-Type: image/jpg"); header("Content-Length: ".filesize($file)); header("Pragma: no-cache"); header("Expires: 0"); $fp = fopen($file, "rb"); while(!feof($fp)) { print(fread($fp, 1024)); flush($fp); } fclose($fp); exit(); ?>

The script itself is fairly easy to understand. First there are a bunch of headers which tell the browser what to do with the file. If you need to serve up other files, just change the MIME type on line 6. You can even force a file to download by using the application/octet-stream type here.

Line 11 opens the file for reading, with the 'b' flag added to force binary-safe reading on Windows servers. The loop just reads in a kB of data and prints it out, with the flush call ensuring it isn't buffered by the browser.

From here, you can add in all sort of things, like obfuscating the filename with an encrypted hash, putting the files in a directory that isn't web-accessible and adding login verification with sessions. Note that in all the tests I've done, media plugins for the browser do not pass across the correct session headers, so you cannot use sessions for audio and video files. I'm not sure if it will be like this for all browser plugins, but at least it was the case for Windows Media Player, Real Player and Quicktime Player.