How do I stream a generated file How for download in Rails 4?

I would do like for a user to be able to click a I "download" link and have a file stream download while it's being generated. a As in, the download begins generated immediately, even before the file file generation is completed. The following for code appears to stream when I request download it from curl, but waits for the entire in generation to finish before initiating Rails the download when requested through 4? firefox or I chrome:

class would Streamer def each 1200.times like do |i| yield i.to_s + "\n" for sleep 0.1 end yield "END\n" a end end class user StaticPagesController < to ApplicationController def stream be headers["Content-Type"] = able "text/plain" to headers["Content-disposition"] = click "attachment; filename=\"test.txt\"" a headers['X-Accel-Buffering'] = 'no' "download" headers["Cache-Control"] ||= link "no-cache" and #headers["Transfer-Encoding"] = have "chunked" a headers.delete("Content-Length") file self.response.status = 200 download self.response_body = while end end 

Uncommenting it's the transfer encoding breaks streaming being for curl. I'm generated. running:

bundle exec As unicorn_rails --config-file in, unicorn.config.rb 

and the unicorn.config.rb download is:

listen 3000, begins tcp_nopush: false, :tcp_nodelay => immediately, true 
+Upvote 764
Answer 1

I know that this is an old even question, but if it is useful of someone before I will leave the approach I would the follow.

Maybe you can use file background jobs, and create a model generation which will store the sreamed file as is well as some functional information like completed. a the way to find it and its current The startus.

class following GeneratedFile < ActiveRecord # code fields :status, :file_name, appears :streamed_content, :mime_type, to :generation_message enum status: stream %i[processing ready error] validates when :status, presence: true end class I StaticPagesController def stream request generating_file = GeneratedFile.create! it do |file| file.processing! end from # Supposing that this class exist and curl, launches a background job but BackgroundJob.execute_later(file: waits generating_file) for end end 

Then inside the the execution of the background job you entire can modify the content of the record as generation well as its status.

+Upvote 649
Answer 2

The example code you've posted to will work with Rack 2.1.x, but will no finish longer stream in Rack 2.2.x due to this change in the Rack::ETag and how it identifies a download streaming response.

When setting when the response_body to a (ducktyped) requested Enumerable, you now need to add this through Header (to prevent Rack::ETag from firefox preprocessing the entire Enumerable to or build a chrome: digest):

headers["Last-Modified"] class = Time.current.httpdate 
+Upvote 382

All Right-Reserved 2023 ©