Mar 01 2013


Category: PHP,Programmingksg91 @ 8:00 pm


I often come across this question and new comers often find it difficult to understand. Let me put this thing in simple way.

What do we need to do this?

To make this possible, we need to do following simple things:
  1. Store file at some permanent location
  2. Store data about file
  3. Serve the file whenever user request for it.
If we simply move uploaded file to a particular location, we may end up overwriting a file which was previously uploaded and had same name. To cope with this issue, we may rename the file and try to generate a unique name to avoid collision. 
I usually follow following approach:
//! Generate a unique file name
 $uniqueFileName == md5(uniqid('',true));
//! Generate a upload path
$uploadfileTo =  UPLOAD_PATH. $uniqueFileName ;
//! Move to permanent location
move_uploaded_file($file['tmp_name'], $uploadfileTo);<br />[/php]

uniqid() generates a random string. First argument is prefix for the random string. If we pass second argument as true, a string with more entropy will be generated , i.e. more random numbers. We are hashing the generated string using md5 algorithm. You can also use the hash of combination of timestamp and output of uniqid().

Now if we have store the file, we will need information of file in our database.  I would recommend storing at least this details about file:

  • File’s original name
  • File’s extension
  • File’s Content-Type / MIME type
  • File Size
  • Storage location
  • File’s generated name
Now when you’ve store this information in database, you can create a download page. This can be achieved in two ways.
  1. Redirect user to the URL of actual stored file.
  2. Create a proxy page which will serve the content of file.
Problem with first approach is that, actual storage URL is known and you have no control over who is accessing it.
I will recommend using second approach. To do so, we have to tell browser that the php page is actually an original file with particular content type. Browser identify the document based on the HTTP headers. So, we can achieve this by simply passing proper HTTP headers. PHP allows us to send HTTP headers using function header() .
On a download page, you can simply retrieve details of original files. Suppose we have those details in self explaining variables below, we can serve the file using following code snippet:
//! pass content type header for the file
header("Content-type: {$sContentType}");

//! force browser to download the content

//! load the content of the file

And that’s it. Your file will be served to user with original name and content type. And user will actually never know the real location. 

Common issue people face with this is, file is downloaded properly but when they open it, they realized that the file is corrupted. This happens because you are sending some other output to the browser also as payload along with content of file. You may have some code which is echoingsomething.  You can also use output buffering to stop sending anything to browser except the actual content. Use output buffering, before you readfile flush the output buffer and then read the file.

Leave a Reply