rails media file stream accept byte range request through send_data or send_file method

Viewed 8154

I have the following problem. Sounds are hidden from the public folder, cause there are only certain Users who should have access to the sound files. So I made a certain method, which acts like a sound url, but calculates first, whether the current user is allowed to access this file.

The file gets sent by the send_data method. The problem is just, that I it works quite slow if it works even... The developer of the jplayer plugin, which I use to play the sound, told me that I should be able to accept byte range requests to make it work properly...

How can I do this within a rails controller by sending the file with send_data or send_file?

Thanks, Markus

4 Answers

I used Garrett's answer and modified it (including one or two bug fixes). I also used send_data instead of reading from a file:

  def stream_data data, options={}
    range_start = 0
    file_size = data.length
    range_end = file_size - 1
    status_code = "200"

    if request.headers["Range"]
      status_code = "206"
      request.headers['range'].match(/bytes=(\d+)-(\d*)/).try do |match|
        range_start = match[1].to_i
        range_end = match[2].to_i unless match[2]&.empty?
      end
      response.header["Content-Range"] = "bytes #{range_start}-#{range_end}/#{file_size}"
    end

    response.header["Content-Length"] = (range_end - range_start + 1).to_s
    response.header["Accept-Ranges"] = "bytes"

    send_data(data[range_start, range_end],
              filename: options[:filename],
              type: options[:type],
              disposition: "inline",
              status: status_code)
  end
Related