Fast, authenticated file downloads with rails, apache and xsendfile
So your rails app manages uploads and downloads of files, be it pictures, documents or other random things the user may wish to store online, and they wish to protect those uploads so only they can access them, via a login and password.
That means you can’t just store all of your files in the public directory and have apache send them out, rails has to get involved to check that you are logged in and have proper access rights.
To do this you can use the send_file method, passing the path to the file (or it’s data if it’s from a db or amazon s3) and the type of file it is.
If you’re using attachment_fu, with a model called Upload it will look something like this:
def download
@upload = Upload.find(params[:id])
send_file @upload.public_filename, :type => @upload.content_type
end
This works fine, but it’s not exactly speedy, and while the file is being sent to the user that rails process has it’s hands completely full, meaning it can’t serve anyone else any pages until it’s done with the file transfer.
In steps mod_xsendfile, a module for apache that also happens to be supported in rails. Below are the brief instructions for installing it for apache on ubuntu:
wget http://tn123.ath.cx/mod_xsendfile/mod_xsendfile.c
apxs2 -cia mod_xsendfile.c
At this point I recieved an error like:
apxs:Error: Activation failed for custom /etc/apache2/httpd.conf file..
apxs:Error: At least one `LoadModule' directive already has to exist..
To fix it I opened the apache config:
sudo nano /etc/apache2/httpd.conf
And pasted this line at the bottom of the file:
LoadModule xsendfile_module /usr/lib/apache2/modules/mod_xsendfile.so
Then restart apache and your server is ready to go:
sudo /etc/init.d/apache2 restart
The last thing to do, is back in your controller, tell rails to utilize xsendfile by passing an extra option to send_file, like this:
def download
@upload = Upload.find(params[:id])
send_file @upload.public_filename, :type => @upload.content_type, :x_sendfile => true
end
All the benefits of rails, with the speed of apache.
Thanks to: gra2, therailsway, and radient for getting me started with this.






