Secure downloads with PHP and mod_xsendfile
It's quite usual to see people sending secure file downloads using either readfile(), fpassthru() or similar. However, this approach for larger files can be troublesome because it goes through the PHP process using higher memory, relies on a high execution time and is slightly slower.
Enter Apache's mod_xsendfile.
What is mod_xsendfile?
It is an Apache 2 module that allows you to set a HTTP header called 'X-Sendfile' which Apache will read, and then send the file referenced to the browser.
Why use mod_xsendfile over the other methods?
When sending big files using readfile() or fpassthru() you may hit the following problems:
- PHP's memory limit
- PHP's max execution time
mod_xsendfile bypasses these two issues.
Setting up mod_xsendfile
After downloading and installing mod_xsendfile (if you're using CentOS for example, you might be able to install by doing a simple 'yum install mod_xsendfile') you need to edit your .htaccess file and add the XSendFile On setting.
#Enable XSendFile XSendFile On
Sending files with PHP
It's quite simple now, infact, just as simple as using readfile()
header('Content-Disposition: attachment;filename=yourfilename.txt'); header('X-Sendfile: /home/username/yourfilename.txt')
That's it. After your PHP script stops executing, apache will see the X-Sendfile header and send the file to the browser. The real location of the file will not be disclosed and you don't need to worry about Content-Length.