Reputation: 2444
I try to stream a huge file from my Rails server my user. My final goal is to stream huge file through my server.
I search and find that I have to use self.response_body
.
So, to test it, I wrote the following code :
class HomeController < ApplicationController
def index
self.response_body = proc {|resp, out|
10.times do |x|
out.write "count = #{x}"
sleep 1
end
}
end
end
But, when I request my Webserver I got the following answer :
curl http://localhost:3000
#<Proc:0x0000010284d048@/Users/nicolas/Documents/development/Ruby/StreamTest/app/controllers/home_controller.rb:4>%
Do you have any idea ?
I'm working with Rails 4.1.4
on a Thin
server
Upvotes: 3
Views: 700
Reputation: 5076
There are a couple of things that need to happen use self.response_body in this manner:
Here's an example:
class HomeController < ApplicationController
def index
headers["Content-Type"] = "text/plain"
headers["Content-disposition"] = "attachment; filename=\"index.txt\""
# Rack::Etag > 2.1.x will break streaming unless Last-Modified is set
headers["Last-Modified"] = Time.current.httpdate
headers['X-Accel-Buffering'] = 'no'
headers["Cache-Control"] ||= "no-cache"
headers.delete("Content-Length")
self.response_body = Enumerator.new do |yielder|
50.times do |x|
# Don't yield integers to the response_body unless you like getting:
# #<NoMethodError: undefined method `bytesize' for 0:Integer
yielder << x.to_s
sleep 0.1
end
end
end
end
One common pitfall to this pattern is that there are similar solutions to this existing on blogs that do not include
headers["Last-Modified"] = Time.current.httpdate
Which only became necessary with the addition of this commit to Rack::ETag in the Rack 2.2.x and beyond.
Upvotes: 4
Reputation: 434
What you are doing here is writing a Proc to the response_body. So the value of your response body will be Proc#to_s. What you want to do is the following:
class HomeController < ApplicationController
include ActionController::Live
def index
response.headers['Content-Type'] = 'text/event-stream'
10.times.each do |x|
response.stream.write "count = #{x}"
sleep 1
end
response.stream.close
end
end
If you want to stream a file you need to consider setting the right response headers.
Upvotes: 0
Reputation: 1392
I think you try to stream output there, here is the documentation
http://api.rubyonrails.org/classes/ActionController/Streaming.html
Upvotes: -1