How to force data to be downloaded as a file from your Rails app

2 July 2007

In the essence of every application is data. One way or another your application manages data and at some point, you need to get that data out. Either you want to synchronize the data with another application or device. Or you want to move your data to another system all together. Either way, you’ll need to gather your data and send it from your application to the client… as a file.

Downloading files is not the hardest thing around. But the problem is that some formats, like XML, are automatically parsed by the browser and this makes it harder for users to download files like that.

So, what you want to do is, ignore the browser and offer your data (in XML or whatever format you want) as a file that can be downloaded directly. The solution is rather easy, as always with Rails.

Okay, in this example I have an action that renders current ‘entries’ as XML and offers this to the user:

def export_to_xml
  @entries = Entry.find(:all)
  render :xml => @entries.to_xml
end

This works as you’d expect it to. When calling this action, the user receives a XML file containing all entries. But really, do you want that in your browser? Especially when the XML file is rather large, this can be very annoying, because your browser will want to load it all in!

What you want here is offer the users a file named ‘entries.xml’ for download. In this case we use Rails’ send_data method. The previous action now looks like this:

def export_to_xml
  @entries = Entry.find(:all)
  send_data @entries.to_xml,
    :type => 'text/xml; charset=UTF-8;',
    :disposition => "attachment; filename=entries.xml"
end

It’s clear that we send the XML data to the client. I specify the type and charset of the data with the ‘type’ paramater. This way the browser knows what is being send and allows the user to choose an application that can use the data. In this case an XML reader, for example.

The disposition parameter tells the browser this should be downloaded as a file (or attachment). It also specifies what the name of the attachment is, ‘entries.xml’.

Now, link to this method and the user will be presented with a downloadable XML file.