PHP file download

So I have been working on a PHP website for a freelance job and had to write few lines of code to download a file from the database. Very simple right? Yeah that’s what I thought too. I mean it was < than 20 lines of code. Why wouldn’t it work? What could go wrong? That’s where I was wrong. This is what I had at first:

if(isset($_GET['id']))
{
  // if id is set then get the file with the id from database
  $id = $_GET['id'];
  $application = new Applications();
  $application->get($id);
  header("Content-length: $application->size");
  header("Content-type: $application->type");
  header("Content-Disposition: attachment; filename=$application->name");
  $content = $application->data;
  echo $content;
}
exit;

The problem I experienced was that a file would upload (different piece of code) fine. I knew that because the size attributes match when the file is written to the db. When I actually try to download the file back from the db using the script above, the file gets corrupted. I had no idea why! The weird (but made sense later) part was that plaintext files were fine no matter how large they were. It was binary files like images, DOCs, PDFs etc. So, I scoured the internet searching for answers and finally came across one thread somewhere where there was a similar discussion from over a year ago and someone said that the file stream would get random whitespace characters when downloading the file. Then it hit me, I remember seeing whitespace at the beginning of the stream when I had opened the corrupt file using notepad. The solution was to ob_clean() before you begin writing the headers and the content stream itself. You see one of the important points about writing header information to the client is that there shouldn’t be any whitespace before writing headers.

I modified the above code then to this:

if(isset($_GET['id']))
{
  // if id is set then get the file with the id from database
  $id = $_GET['id'];
  $application = new Applications();
  $application->get($id);
  ob_clean(); //clears output buffer in php..see php manual
  header("Content-length: $application->size");
  header("Content-type: $application->type");
  header("Content-Disposition: attachment; filename=$application->name");
  $content = $application->data;
  echo $content;
}
exit;

It would then download without any problems. At this time I should also caution you about dangling newline/whitespace in the php file itself which handles the download. The reason why plaintext files were ok is because plaintext files are not written in binary so whitespace or not it doesn’t matter for those file types and they will upload/download fine, at least in my case they did. Do you have a better way to handle this? If so, please leave a comment. Let me know about it.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s