Simple PHP File Download Script

Programming31468

So I recently added a download.php script to my website so that I could force downloads of files instead of having users access them through an indexed directory or through their browser.

I found various scripts online but none of them were as clean as I'd have liked them to be so I wrote my own simple script after a bit of research.

In my setup, the download.php file sits at the root of my website and the filevault folder sites one level higher on the web server. This setup ensures users cannot hotlink to files or directly access them, the script must be used. A benefit of this is that you can add restrictions like allowing a file to be accessed by people from a particular country or by those who have a certain cookie set. If you do not have access to the directory above your websites root directory then you are forced into putting your filevault at the websites root directory.

This is the simple PHP File download script:

<?php

/*
 *  Download File script
 *  Aurthor: Mo Beigi
 *  Url: https://mobeigi.com
 *  Usage: /download.php?file=XXXX
 *
*/

ignore_user_abort(true);
set_time_limit(0); // disable the time limit for this script

if (!empty($_GET['file'])) {
  $path_parts = pathinfo($_GET['file']);
  $file_name  = $path_parts['basename'];
  $path_to_filevault_dir = "../filevault";
  
  //Build absolute file path
  $path_to_file  = $path_to_filevault_dir . '/' . $file_name;
  
  //Check if file exists
  if (!file_exists($path_to_file)) {
    
    print '<div>Invalid file specified. Please notify the webmaster if you think this is a mistake.</div>';
    exit(1);
  }
  
  //Check if file is readable
  if (!is_readable($path_to_file)) {
    print "An error has occurred. Please notify the webmaster.";
    exit(1);
  }
  
  # detect MIME type (http://stackoverflow.com/a/32092523/1800854)
  $finfo = finfo_open(FILEINFO_MIME_TYPE);
  header('Content-Type: ' . finfo_file($finfo, $path_to_file));
  
  $finfo = finfo_open(FILEINFO_MIME_ENCODING);
  header('Content-Transfer-Encoding: ' . finfo_file($finfo, $path_to_file)); 

  header('Content-disposition: attachment; filename="' . basename($path_to_file) . '"'); 

  readfile($path_to_file);
}
else {
  print "'file' parameter is missing and is required.";
  exit(1);
}

?>

Usage

The following link would force the download of that_file.txt

https://example.com/download.php?file=that_file.txt

Demo

You can also download the above script:

download.php

Leave a comment

(required)(will not be published)(required)

Comments

Showing 8 comments from 6 commenters.

  • Display picture for Santhosh veer
    Santhosh veer

    Hey thanks for this code

    I found little error on this code

    if ($_GET['file'] != "") { on line no 14

    Replace it with if (isset($_GET['file'])) {

    and in $path_to_filevault_dir = "../filevault"; remove that two ".." full stops

    Thanks for this awesome script :)

    Reply
    • Display picture for Mo Beigi
      Mo Beigi

      Good call about the $_GET check, i've changed the script to instead use (!empty($_GET['file'])) which will check if isset as well as if its an empty string.

      However, the $path_to_filevault_dir is not an error. The file vault folder is meant to be located in a non accessible folder on the machine so users can't directly download the file by avoiding the script. However, you could simply place it somewhere else if you really want.

      Reply
  • Display picture for Mo Beigi
    Mo Beigi

    Cleaned up the above code a little to fix an issue with downloading files with a space in their name.

    Reply
    • Display picture for Hue
      Hue

      Great script but doesn't seem to like https.

      Strangely, It works if i delete the checks:

      (Check if file exists & Check if file is readable).

      Any ideas?

      Reply
      • Display picture for Mo Beigi
        Mo Beigi

        Works fine for HTTPS, my site is HTTPS only. Double check the $path_to_filevault_dir and make sure its pointing to the correct file vault directory relative to the scripts location.

        Reply
  • Display picture for raj
    raj

    perfect script but not show in my website

    Reply
  • Display picture for Alex
    Alex

    I could not download the file when I added the file source from another site as a link.

    $ path_to_filevault_dir = "http://www.example.com/example/download/";

    Is there a method to use in this way?

    Thanks.

    Reply
  • Display picture for Gareth Markey
    Gareth Markey

    Having a similar problem to the one mentioned above. I have placed this file in my root directory as filename dlf.php and changed the $path_to_filevault_dir = "/download"; as my PDF files for downloading are located in sub Folder /download.

    The link for my file is <a href="dlf.php?filename=Rules.pdf" rel="nofollow">Clicking Here</a>

    however when I click on the file to download I receive the following message

    'file' parameter is missing and is required.

    Any suggestions?

    Reply