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

后端 未结 4 1653
走了就别回头了
走了就别回头了 2020-11-30 05:20

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 met

4条回答
  •  情深已故
    2020-11-30 05:49

    Here is my version. I use gem 'ogginfo-rb' to calculate the duration which is required to serve ogg files properly. p.s. I always have three formats - wav, mp3, ogg.

    the_file = File.open(file_path)
    
    file_begin = 0
    file_size = the_file.size
    file_end = file_size - 1
    
    if request.headers['Range']
      status_code = :partial_content
    
      match = request.headers['range'].match(/bytes=(\d+)-(\d*)/)
    
      if match
        file_begin = match[1]
        file_end = match[1]  if match[2] and not match[2].empty?
      end
    
      response.headers['Content-Range'] = "bytes #{file_begin}-#{file_end.to_i + (match[2] == '1' ? 1 : 0)}/#{file_size}"
    else
      status_code = :ok
    end
    
    response.headers['Content-Length'] = (file_end.to_i - file_begin.to_i + 1).to_s
    response.headers['Last-Modified'] = the_file.mtime
    
    response.headers['Cache-Control'] = 'public, must-revalidate, max-age=0'
    response.headers['Pragma'] = 'no-cache'
    response.headers['Accept-Ranges'] = 'bytes'
    response.headers['Content-Transfer-Encoding'] = 'binary'
    
    require 'ogginfo-rb'
    ogginfo = Ogg::Info::open(the_file.path.gsub(/.mp3|.wav/,'.ogg'))
    duration = ogginfo.duration.to_f
    
    response.headers['Content-Duration'] = duration
    response.headers['X-Content-Duration'] = duration
    
    send_file file_path,
              filename: "#{call.id}.#{ext}",
              type: Mime::Type.lookup_by_extension(ext),
              status: status_code,
              disposition: 'inline',
              stream: 'true',
              buffer_size: 32768
    

提交回复
热议问题