la secuencia de archivos multimedia de los Rails acepta la solicitud de rango de bytes a través del método send_data o send_file

Tengo el siguiente problema. Los sonidos están ocultos de la carpeta pública, porque solo hay ciertos usuarios que deberían tener acceso a los archivos de sonido. Así que hice un cierto método, que funciona como una url de sonido, pero primero calcula si el usuario actual tiene permiso para acceder a este archivo.

El archivo se envía mediante el método send_data. El problema es que funciona bastante lento si funciona, incluso … El desarrollador del plugin jplayer, que uso para reproducir el sonido, me dijo que debería poder aceptar solicitudes de rango de bytes para que funcione correctamente. …

¿Cómo puedo hacer esto dentro de un controlador de Rails enviando el archivo con send_data o send_file?

Gracias, Markus

He podido servir los archivos con cierto éxito usando send_file. Aunque tengo un problema, buscar una parte anterior de la canción provoca una nueva solicitud que hace que la canción se reinicie a partir de las 0:00 en lugar de la ubicación verdadera desde la barra de búsqueda. Esto es lo que tengo trabajando para mí hasta ahora:

file_begin = 0 file_size = @media.file_file_size file_end = file_size - 1 if !request.headers["Range"] status_code = "200 OK" else status_code = "206 Partial Content" match = request.headers['range'].match(/bytes=(\d+)-(\d*)/) if match file_begin = match[1] file_end = match[1] if match[2] && !match[2].empty? end response.header["Content-Range"] = "bytes " + file_begin.to_s + "-" + file_end.to_s + "/" + file_size.to_s end response.header["Content-Length"] = (file_end.to_i - file_begin.to_i + 1).to_s response.header["Last-Modified"] = @media.file_updated_at.to_s response.header["Cache-Control"] = "public, must-revalidate, max-age=0" response.header["Pragma"] = "no-cache" response.header["Accept-Ranges"]= "bytes" response.header["Content-Transfer-Encoding"] = "binary" send_file(DataAccess.getUserMusicDirectory(current_user.public_token) + @media.sub_path, :filename => @media.file_file_name, :type => @media.file_content_type, :disposition => "inline", :status => status_code, :stream => 'true', :buffer_size => 4096) 

Aquí está mi versión. Utilizo gem ‘ogginfo-rb’ para calcular la duración requerida para servir correctamente los archivos ogg. ps. Siempre tengo tres formatos: 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 

Otra versión modificada: estaba intentando descargar un archivo zip como contenido binario y esto es lo que funcionó para mí:

  def byte_range_response (request, response, content) file_begin = 0 file_size = content.bytesize file_end = file_size - 1 status_code = '206 Partial Content' match = request.headers['range'].match(/bytes=(\d+)-(\d*)/) if match file_begin = match[1] file_end = match[2] if match[2] && !match[2].empty? end content_length = file_end.to_i - file_begin.to_i + 1 response.header['Content-Range'] = 'bytes ' + file_begin.to_s + '-' + file_end.to_s + '/' + file_size.to_s response.header['Content-Length'] = content_length.to_s response.header['Cache-Control'] = 'public, must-revalidate, max-age=0' response.header['Pragma'] = 'no-cache' response.header['Accept-Ranges']= 'bytes' response.header['Content-Transfer-Encoding'] = 'binary' send_data get_partial_content(content, content_length, file_begin.to_i), type: 'application/octet-stream', status: status_code end def get_partial_content(content, content_length, offset) test_file = Tempfile.new(['test-file', '.zip']) test_file.puts(content) partial_content = IO.binread(test_file.path, content_length, offset) test_file.close test_file.unlink partial_content end