2013-05-08 20 views
9

我們在使用默認的rails 3應用程序在ipad上播放mp4時遇到問題。當在桌面上的chrome和其他瀏覽器中查看路由時,mp4會正確提供服務。通過導軌將Ipad服務到mp4文件的正確方法是什麼?

這裏是我們的代碼:

file_path = File.join(Rails.root, 'test.mp4') 
send_file(file_path, :disposition => "inline", :type => "video/mp4") 

我們打0.0.0.0:3000/video/test.mp4觀看視頻,並呈現在iPad上無法播放圖標。我們嘗試修改各種標題「Content-Length」,「Content-Range」等,但它們似乎並未影響最終結果。

我們還使用SEND_DATA在一定程度上

File.open(file_path, "r") do |f| 
    send_data f.read, :type => "video/mp4" 
end 

在iPad上觀看時,相同的視頻服務從公用文件夾精細嘗試。

什麼是正確的方式來通過導軌爲ipad服務mp4文件?

回答

15

問題似乎是rails不處理ios需要流式傳輸mp4的http範圍請求。

這是我們發展的解決方案,(用細如我們的服務器):

if(request.headers["HTTP_RANGE"]) && Rails.env.development? 

    size = File.size(file_path) 
    bytes = Rack::Utils.byte_ranges(request.headers, size)[0] 
    offset = bytes.begin 
    length = bytes.end - bytes.begin + 1 

    response.header["Accept-Ranges"]= "bytes" 
    response.header["Content-Range"] = "bytes #{bytes.begin}-#{bytes.end}/#{size}" 
    response.header["Content-Length"] = "#{length}" 

    send_data IO.binread(file_path,length, offset), :type => "video/mp4", :stream => true, :disposition => 'inline', 
       :file_name => file_name 

    else 
    send_file(file_path, :disposition => 'inline', :stream => true, :file_name => file_name) 
    end 

最終,我們將使用nginx的XSendfile服務於資產在我們的生產環境上面的解決方案比慢得多了什麼我們需要。

+2

我認爲在代碼中有一個fencepost錯誤。我相信長度應該是'bytes.end - bytes.begin + 1' - 如果字節範圍是從字節10到12,那應該是3個字節。另外,如果你出於某種原因使用'send_data',一定要在響應頭中設置'Content-Length'。 – tovodeverett 2013-09-17 23:47:22

+0

謝謝你的解決方案!我根據@tovodeverett評論添加了更正。使用Sinatra(而不是Rails)進行開發,我設法使用sinatra/streaming contrib複製send_data行爲,如下所示:'stream {| out | out.write IO.binread(file_path,length,offset); out.flush}' – 2015-11-05 14:43:55

+1

感謝您的解決方案!我們注意到,爲了使這種方法在Chrome中工作,必須明確地將響應狀態設置爲'206'。 – 2017-10-11 12:07:28

相關問題