Managing Database Files with Ruby on Rails - Sending Data with X-Sendfile (Page 2 of 4 )
Often you will need to send a file to the client for download after doing some processing in Rails. The most common example is an access-controlled file--you need to verify that the logged-in user has the appropriate level of access before sending the file, for example. The easy way to do this is with the send_file or send_data API calls, which stream data from the server to the client:
class DataController < ApplicationController before_filter :check_authenticated
def private_document file = File.find params[:id] send_file file.path if file end
end
This method is easy, but it is slow if you are sending static files. Rails reads the file and streams it byte-by-byte to the client. The X-Sendfile protocol makes this easy and fast, by allowing Rails to do its processing but then offloading the "heavy lifting" to the web server (which may offload that processing to the operating system kernel, as described previously).
The X-Sendfile protocol is a very simple standard, first introduced in the Lighttpd web server, which directs the web server to send a file from the filesystem to the client rather than a response generated by the application server. Because the web server is optimized for throwing files at the client, this usually yields a decent speed improvement over reading the file into memory and sending it from Rails with the send_file or send_data API calls.
Because the web server requires access to the file in order to send it to the client, you must use filesystem large object storage. In addition, the files to be sent must have permissions set so as to be accessible to the web server. However, the files should be outside of the web root, lest someone guess a filename and have free access to your private files.
X-Sendfile uses the X-Sendfile HTTP header pointing to the servers path to the file to send, in conjunction with the other standard HTTP headers. A typical response using X-Sendfile would look something like this: