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 = Streamer.new 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
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.
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