2011-07-20 1 views
8

次の問題があります。サウンドはパブリックフォルダから隠されます。サウンドファイルにアクセスする必要のある特定のユーザーのみが存在するためです。だから私は、サウンドurlのように動作する特定のメソッドを作ったが、現在のユーザーがこのファイルにアクセスすることが許可されているかどうか最初に計算します。railsメディアファイルストリームsend_dataまたはsend_fileメソッドによるバイト範囲要求を受け入れる

ファイルはsend_dataメソッドによって送信されます。問題はちょうど、私はそれが動作する場合は非常に遅く動作することです...サウンドを再生するために使用するjplayerプラグインの開発者は、バイト範囲の要求を受け入れて、正しく動作させることができるはずだと教えてくれました...

ファイルをsend_dataまたはsend_fileで送信すると、これをどのようにしてレールコントローラ内で行うことができますか?

おかげで、 マルクス

+0

Webサーバを使用していますか? – NARKOZ

+0

apache 2 with passenger modul – Markus

+0

https://gist.github.com/mikhailov/3174601を試してみましたか? – Anatoly

答えて

8

私はsend_fileを使用してある程度の成功を収めたファイルを果たすことができました。私は1つのヒッチを持っていますが、曲の早い部分を探すことは、シークバーからの真の場所の代わりに0:00から曲を再開させる新しい要求を引き起こします。これはこれまでの私の仕事です:

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) 
+2

私はこれを試してみました。ストリーミングオプション(:streamと:buffer_size)は実際には必要ありません。 –

1

ここは私のバージョンです。私はgem 'ogginfo-rb'を使って、oggファイルを適切に提供するのに必要な時間を計算します。 p.s.私はいつもwav、mp3、oggという3つのフォーマットを持っています。

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 
+0

'Accept-Ranges'ヘッダーの周りの部分は、バイト範囲を送信するようNGINXに指示するために必要なものです。私たちは、オーディオだけでなく、いくつかのタイプのビデオも送信しているので、Content-Durationに頼ることはできません。だから私たちはその部分をスキップして、うまくいくように思えます。 –

0

別の修正版 - 私は、バイナリコンテンツとしてzipファイルをダウンロードしようとしていた、これは私のために働いていたものです -

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 
関連する問題