Last Updated: February 25, 2016
·
8.102K
· descentintomael

Streaming Files in Rails

Rails has send_data and send_file. The latter works with blobs of data and the former works with files on the server. Blobs of data only work if you already have that in memory and files breakdown once you have multiple servers. What if you want to stream out to the browser as you read in from the database?

You can create a streamer object to hand off data as you fetch it from the database. You just need to set the response body to an object that response to each.

Put this in your controller:

def download
  report = StoredReport.first

  headers["Content-Type"] = "text/csv"
  headers["Content-disposition"] = "attachment; filename=test.csv"

  self.response_body = StoredReportStreamer.new(report)
end

Be sure to include the header stuff to mark it as the correct type and as a download.

Then for the streamer object use this:

class StoredReportStreamer
  attr_accessor :report

  def initialize(report)
    self.report = report
  end

  def each
    report.rows.each do |row|
      yield row
    end
  end
end

That will yield each row of the report out to the browser.

Thanks to this blog post for the tip: http://blog.sparqcode.com/2012/02/04/streaming-data-with-rails-3-1-or-3-2/

4 Responses
Add your response

In Rails 4 there is new approach: https://gist.github.com/lexmag/3259481

And sinatra example: https://gist.github.com/lexmag/3260374

over 1 year ago ·

You specify this for the content-type:

response.headers['Content-Type'] = 'text/event-stream'

Doesn't this only go to WebSocket stuff and not a file? My tip is specifically geared towards streaming to a file download.

Anyways, thanks for the examples.

over 1 year ago ·

Yes, my examples aren't about file streaming.
text/event-stream is for Server-Sent Events. I think worth to understand the approach of streaming in general.

over 1 year ago ·

How do you catch an exception inside 'each' method and show it nicely to user?. I have this issue: http://stackoverflow.com/questions/31681519/ruby-on-rails-3-streaming-data-and-catching-exception

over 1 year ago ·