2011-07-20 18 views
8

Tôi gặp sự cố sau. Âm thanh được ẩn khỏi thư mục công cộng, vì chỉ có một số Người dùng nhất định có quyền truy cập vào các tệp âm thanh. Vì vậy, tôi đã thực hiện một phương pháp nhất định, hoạt động giống như một url âm thanh, nhưng tính toán trước tiên, cho dù người dùng hiện tại có được phép truy cập tệp này hay không.luồng tệp phương tiện truyền thông đường ray chấp nhận yêu cầu phạm vi byte thông qua phương thức send_data hoặc send_file

Tệp được gửi bằng phương thức send_data. Vấn đề là, tôi hoạt động khá chậm nếu nó hoạt động ... Nhà phát triển plugin jplayer mà tôi sử dụng để phát âm thanh, nói với tôi rằng tôi có thể chấp nhận yêu cầu phạm vi byte để làm cho nó hoạt động bình thường ...

Làm cách nào để thực hiện điều này trong bộ điều khiển đường ray bằng cách gửi tệp có send_data hoặc send_file?

Cảm ơn, Markus

+0

mà máy chủ web bạn đang sử dụng? – NARKOZ

+0

apache 2 với modul hành khách – Markus

+0

bạn đã thử https://gist.github.com/mikhailov/3174601 chưa? – Anatoly

Trả lời

8

tôi đã có thể để phục vụ lên các tập tin với một số thành công sử dụng send_file. Mặc dù tôi có một sự cố, việc tìm kiếm một phần trước của bài hát gây ra một yêu cầu mới khiến bài hát khởi động lại từ 0:00 thay vì vị trí thực sự từ thanh tìm kiếm. Đây là những gì tôi đã làm việc cho tôi cho đến thời điểm này:

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

tôi vừa thử điều này và nó hoạt động. các tùy chọn phát trực tuyến (: stream và: buffer_size) không thực sự cần thiết ở đây. –

1

Đây là phiên bản của tôi. Tôi sử dụng gem 'ogginfo-rb' để tính thời lượng cần thiết để phục vụ các tệp ogg đúng cách. p.s. Tôi luôn có ba định dạng - 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 
+0

Phần xung quanh tiêu đề 'Accept-Ranges' là chính xác những gì cần thiết, với công cụ NGINX mà nó gửi các dãy byte. Chúng tôi không thể dựa vào Thời lượng nội dung, bởi vì chúng tôi không chỉ gửi âm thanh, mà còn một số loại video nữa. Vì vậy, chúng tôi bỏ qua phần đó, và điều đó dường như hoạt động tốt. –

0

Một phiên bản sửa đổi - Tôi đã cố gắng để tải về một file zip như nội dung nhị phân và đây là những gì làm việc cho tôi -

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 
Các vấn đề liên quan