Downloading files with download.php

You could use .htaccess to redirect the request to the file while keeping the permalink structure:

RewriteEngine On
RewriteBase /
RewriteRule ^download\/([^\/]+)\/file.zip download.php?id=$1 [L,NC]

Then in your download.php, you can check if the provided id is valid:

// Path to file
$file = 'file.zip';

// If the ID is valid
if ($condition) {
    header("Content-Disposition: attachment; filename=\"" . basename($file) . "\"");
    header("Content-Type: application/force-download");
    header("Content-Length: " . filesize($file));
    header("Connection: close");
} else {
    // Handle invalid ids
    header('Location: /');
}

When the user visits a valid url http://example.com/download/f6zDaq/file.zip, the download will start and the connection will be closed.

If the user visits an invalid url, they will be redirected to the home page.


The biggest problems you're going to face with files of those sizes are the following:

  • people downloading it with a download manager
  • interrupted connections

Normally, keep-alive can be a bad idea, as it dedicates a connection to a download, which can bog down your network connections instead of allowing them to be freed up easily. However, if you're expecting all of your files to be large, this is your friend, because you don't want people re-starting those downloads. And those downloads will make reliable connections with keep-alive, and be easier for the client to resume which helps reduce people trying to re-download massive files.

As such, of your presented options, I recommend

1ter

However, as others on here, I still recommend you test your solutions, and preferably from a location separate than you're serving the files from.

Addendum: This said, serving with PHP isn't the best idea unless you have to get the header control features and .htaccess control in, because it's just adding more processing power. By far the better path would be simply to have the files in an accessible directory. .htaccess can rewrite access to files and folders, not just PHP scripts.

To create Apache-based protected download folders instead:

Options +FollowSymLinks
RewriteEngine On
RewriteRule ^/user/files/folder1.*$ http://example.com/userfiles/ [R=301,L]

Then, if you need to password-protect it, instead of using PHP, use Apache (which is already installed with most PHP installations). You do this by including a .htaccess file in the targeted folder (if you're dynamically making users, you might need to create a script to generate these for each new user) and making sure apache is prepped to handle passwords:

AuthType Basic
AuthName "Authentication Required"
AuthUserFile "/user/password/.htpasswd"
Require valid-user

(See here for more detail: Setting up Apache Passwords)

After this point, you make sure to have an .htpasswd file in the password directory with the format username:password/hashedpassword.

e.g.:

andreas:$apr1$dHjB0/..$mkTTbqwpK/0h/rz4ZeN8M0
john:$apr1$IHaD0/..$N9ne/Bqnh8.MyOtvKU56j1

Now, assuming you're not wanting them to pass in the password every single time, in the download link, include the access

<a href="user:pass@http://example.com/userfiles/myCoolZip.zip">Link (hopefully behind a password-protected interface.)</a> 

[Note: Do NOT use the direct password link method if passwords are not randomly assigned per file.]

OR if you're populating based off of the root apache password management AND your site is utilizing apache for it's login process, they might not need the user:pass part of the link at all, having already logged in with Apache.

NOTICE:

Now, this said, the files will be be accessible by people that the full link (with username/password) are shared with. So they'll be as secure (or as unsecure) as your server's https (or http if you allow) protocols, as well as your users sharing or not-sharing links.

Doing it this way, the files will be open to the users it's meant for with the full capabilities of the web accessible to them, meaning download helpers, browser-plugins that help, REST calls, and more, depending on your user's use cases. This can reduce security, which may or may not be a big deal depending on what you're hosting. If you're hosting private medical data (few users, high security, lower speed demands), I wouldn't do it this way. If you're hosting music albums, I'd totally do it this way (many users, lower security, high speed demands).


I would go with readfile. I used it for years, and never got memory issues, even running on a 128MB VPS.

Using PHP means you can easily handle authentication, authorization, logging, adding and removing users, expiring URL and so on. You can use .htaccess to do that, but you will have to write a rather large structure to handle this.