PHP - Protected download

In this example, we are protecting a file from an unauthenticated download.
The script will ask for username and password, and if it is OK, it will send a file. Notice, that we do not give file URL. We are sending file through PHP script, so the real location of the file stays secret for the outside world. The downside is that a user cannot continue an interrupted download.
Depending on the server configuration, you may not have sufficient permissions to use mime_content_type (it is disabled by default). If this is a situation, just hardcode your MIME type.

<?php
if (isset($_POST["username"]) && ($_POST["username"] == "phpbee") &&
    isset($_POST["password"]) && ($_POST["password"] == "phpbee"))
  SendFile();
else
  DisplayLoginPage();
function DisplayLoginPage()
{
?>
<html>
  <head>
    <title>Protected download</title>
  </head>
  <body>
    <h2>Welcome to download area</h2>
    <p> Type username and password to download a file </p>
    <p> Type phpbee for both username and password </p>
    <form action="download.php" method="post">
      Username<br>
      <input type="text" name="username"><br>
      Password<br>
      <input type="password" name="password"><br>
      <input type="hidden" name="login"><br>
      <input type="submit">
      <input type="reset">
    </form>
  </body>
</html>
<?php
}
function SendFile()
{
  $FileName = "filename.zip";
  //header("Content-Type: " . mime_content_type($FileName));
  // if you are not allowed to use mime_content_type, then hardcode MIME type
  // use application/octet-stream for any binary file
  // use application/x-executable-file for executables
  // use application/x-zip-compressed for zip files
  header("Content-Type: application/octet-stream");
  header("Content-Length: " . filesize($FileName));
  header("Content-Disposition: attachment; filename=\"$FileName\"");
  header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
  $fp = fopen($FileName,"rb");
  fpassthru($fp);
  fclose($fp);
}
?>

Related Marakana Courses

  • PHP and MySQL Bootcamp Training

14 Responses to “PHP - Protected download”

  1. Mrx Says:

    Parse error: syntax error, unexpected ':' in /home/cafe-galleri/web/cafe-galleri.no/download.php on line 39

    i get that error, line 39 is header(Content-Type: application/octet-stream);

    what's wrong?

  2. bunn Says:

    yeah it gives me:

    Warning: Cannot modify header information - headers already sent by (output started at /home/www/longpoke.us.to/lp/x.php:7)

    wtf mate i was liking the code too :O

  3. bunn Says:

    oh nvm now i see how it works :)

  4. Kor Says:

    h?mm it needs ob_start(); at the beginning and ob_flush(); for the " Cannot modify header information " problem :)
    however when I run this code it downloads my page not the file? is there any problem with header or is it a configuration issue of the server?

  5. Scot Blankenship Says:

    jfw9y3b5ork1r41e

  6. nur Says:

    thank you

  7. Юлиан Says:

    Вполне возможно. Иногда так действительно случается.

  8. BadBoy Says:

    Если это не большой секрет;), автор блога откуда родом?

  9. sandrar Says:

    Hi! I was surfing and found your blog post… nice! I love your blog. :) Cheers! Sandra. R.

  10. angelina jolie Says:

    I love your site. :) Love design!!! I just came across your blog and wanted to say that Ive really enjoyed browsing your blog posts. Sign: ndsam

  11. Johnathon Hayward Says:

    Thanks, this has been very helpful code, especially when combined with ob_start, ob_flush as Kor suggested.

  12. DavidMoreen Says:

    Hey thanks a lot for this, really helpful. I just wish that there was a little more security.

  13. lee parmenter Says:

    Hi All,

    This code seems to work perfectly as written when run on a uni*/linux machine. However, it appears that if it is run under Windows (I have XP Pro), the only way PHP sees the file to be downloaded is if the file is in the same folder as the PHP code resides. Relative or absolute URLs have no effect, apparently. If I place the download file in some other part of the document tree (i.e., ../tmp/somefile.zip), windows doesn't know what to do with it and downloads the download.php file instead. I tried using the reverse backslash (as sometimes required in Windows environments ..\tmp\somefile.zip) to no avail. If I have more time, I'll try to isolate this issue because it is quite unusual for PHP to be this inconsistent across platforms, except for OS specific restrictions, such as file naming conventions and so on. I don't ever remember running into something like this, and I've been working with PHP since version 3.0.

  14. Johnathon Hayward Says:

    I was using this code happily until I discovered it didn't work for two of my larger files (48mb and 50mb), however it worked with a 31mb file. I would really love to know how to do a protected download with larger files. If anyone knows a way, please post it here. Thanks!

Leave a Reply