PHP download file script

This is my favorite PHP download script. I’ve used a different more simple method until a client wanted to be able to allow their site visitors to download a large file from a password protected directory. The PHP script works on Apache web servers for all kind of files. I have used this script for file downloads bigger than 500MB. The cache control header is used to force the download for text files and other files even if they are opened by default inside your web browser.

How to use the PHP download file script?

Create a PHP script, name it “download.php” and copy/paste the following code:

Create on your webpage links for each file which resists in a password protected directory or in a directory above the website root directory. Use for our example the following download URL:

PHP Download FilePHP download file features:

  • The file name, which is passed via the query string, is sanitized by using the PHP function preg_replace() and filter_var()
  • To make the script safer, I use the PHP function pathinfo() to parse the file path, if this happens successfully, the script will continue the further file handling process.
  • The file download script is also created for bigger files (using this script I’ve downloaded files bigger than 500MB!).

Script Demo

The demo page demonstrates the PHP code examples for file upload and download and PHP directory functions to show files in SELECT menu.

PHP download files from a MySQL database

The PHP download code doesn’t hide the file name and in some situations it might be better to use a unique string or ID as a key for the download. With the following example, I will use a string to receive the name of a file which is stored inside a MySQL database. Let say we have a simple database table with only two columns for the ID and the filename. The code for the download.php is almost the same and only the first part is different:

How to use that PHP/MySQL download code?

In the first example I used the file name right in my download URL. Because I’m casting the md5 encryption with $secret as the salt, I need to built my file download URL differently:

Disclaimer

I published the PHP download example code to explain how a file download using a PHP script. If you really need to protect your downloads, you need to deny the direct access a safe location or .htaccess rules. Use more secure slugs to receive a file name from your database. For example you can encrypt the database row key as well. 

15 thoughts on “PHP download file script

  1. In the modern world, your server should support the “sendfile” method to offload the transfer of the file after authentication is done.

    IIRC mod_sendfile in Apache, x-accel-redirect in nginx

    Otherwise you’re just blocking that php engine until the client has closed the connection.

    • Hi Mike,
      “Sendfile” looks great and I’m sure I will use this mod for the next heavy downloads server I use. The problem is that mod_xsendfile isn’t installed on most of the (shared) hosting accounts. I guess that’s one reason why there are so many people looking for a 100% PHP download solution. For Nginx (I will try that one for sure) is this article interesting:
      http://kovyrin.net/2006/11/01/nginx-x-accel-redirect-php-rails/ (LOL this feature exists for more than 10 years)

    • Mike,

      I see that mod_xsendfile is still in beta: https://tn123.org/mod_xsendfile/
      I’m sure the mod is great way to process downloads, but I don’t think that a lot of server admins will install the mod on their production servers. This will make it a more developer solution, don’t you think?

      • I ditched Apache so many years ago… I thought it was practically shipped with nowadays. Wow. That’s sad.

        Just another reason to switch to an nginx-based solution. I think lighty has supported it for a long time too.

      • Let’s keep us the discussion about LightHTTP, Apache and Nginx for another topic :)
        Thanks for your insights!

  2. Then they should move away from shared hosts. It’s in their interest to enable things like sendfile. They probably still run mod_php and have lame permissions crap too.

    • Sure they should move away, but many of them stick with shared hosting because of the higher costs for managed server hosting. This website is a VPS by DigitalOcean and I’m using ServerPilot as a kind of control panel. I can’t use mod_sendfile because it’s not enabled, but I will check the Nginx variant.

  3. Hi, i used your code to create a download.php file, in order to protect my files from !$_SESSION users. I would like to protect also my folder from url access, if i use 700 as chmod value, the page will not return the download file, but it will stay blank (the fopen fail).. Which value should i use for access files from the code?

    • Hi Marcello,
      Using a file permissions or CHMOD is the wrong way in some situations. It’s better to move your downloads to a level “above” the public_html directory. Or protect your directory via .htaccess and .htpasswd.
      Does the download work with regular permissions?

      • i’ve just solved 5 mins ago via .htaccess. I deny the access to the folder.
        My file’s paths are stored in a database table, so i pass only the ID via GET method. The “noob” user will never see the clear URL of the file.

        The download works with regular permission. Thanks!

    • Hi Olaf,
      I notice that i have some problems on file download via Internet Explorer and Safari. The script gave me an empty file. Do you know what i’m talking about?

      Thanks in advance

      • Hi,

        sounds like a problem with headers, does the same script works for you in browsers like Chrome and Firefox?
        Do you use the windows versions?

  4. Warning: Cannot modify header information – headers already sent by (output started at C:\wamp\www\Backup\Sec_Academic\test.php:9) in C:\wamp\www\Backup\Sec_Academic\test.php on line 374

    Line 374: Is the one that has the header function ie header(“Content-type: application/octet-stream”);
    This warning is displayed for all header function used after the default key word in the Switch function

    How can i fix this?

    • Hi Bobic,

      like the warning said your script started the output at row 9. Is there an “echo” or some empty row/whitespace?

Comment Rules

Don’t post your code here, post your code block or snippet to pastebin and include the pastebin URL in your comment.

I delete all comments with non related links inside the comment text. Don't use keywords for the field of your real name (most people like to use your name for their answer). Keep your comment related to the topic, if your question is off-topic, please use the contact form instead.

Leave a Reply

Your email address will not be published. Required fields are marked *

*
*
Website