Dennis
Dennis

Reputation: 1975

How can I do event on downloads on Rails5?

I cannot find anything on neither Documentations nor Google about resumable downloads on Rails (Ruby)

I am using Ruby 2.4 and Rails 5.0.1 on Linux. I want to let my users to download a file over rails. When download starts I want to let them pause and resume it. And, on each requested block I want to execute some functions (events maybe).

I can do that on PHP/Laravel5. I can provide resumable downloads and i can run code on each requested part.

I cannot find anything about this on Rails' website or Google. Is this giant framework not capable of doing it?

Big Note:

I am not talking about directly downloading files. I want to control each part. When from x byte to y byte requested, I want to execute some code before they deliver that part.

Any ideas?

Upvotes: 1

Views: 121

Answers (1)

Eric Duminil
Eric Duminil

Reputation: 54263

Streaming

This article and the official documentation are informative.

class DownloadingController < ActionController::Base
  include ActionController::Live

  def stream
    response.headers['Content-Type'] = 'text/event-stream'
    (params[:from].to_i..params[:to].to_i).each { |i|
      response.stream.write "hello world #{i}\n"
      sleep 1
    }
  ensure
    response.stream.close
  end
end

with routes.rb :

get 'downloading' => 'downloading#stream'

Launching :

curl -i "http://localhost:3000/downloading?from=10&to=20"

outputs :

HTTP/1.1 200 OK
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Content-Type: text/event-stream
ETag: W/"1f373c782d25c8d804203b14291b315b"
Cache-Control: max-age=0, private, must-revalidate
X-Request-Id: 53337282-e382-4807-bdf9-cbf689ac24b2
X-Runtime: 21.048071
Transfer-Encoding: chunked

hello world 10
hello world 11
hello world 12
hello world 13
hello world 14
hello world 15
hello world 16
hello world 17
hello world 18
hello world 19
hello world 20

Resuming

If you want to resume a previous download, you'll have to check request.headers["Range"] and set :status => "206 Partial Content" as well as response.header["Accept-Ranges"] = "bytes".

Those two answers might help you.

Upvotes: 2

Related Questions