Bru*_*pos 4 ruby ruby-on-rails video-streaming ruby-on-rails-3.2
我有一个Rails应用程序,可以保护上传的视频,将它们放入私人文件夹.
现在我需要播放这些视频,当我在控制器中执行此类操作时:
def show
video = Video.find(params[:id])
send_file(video.full_path, type: "video/mp4", disposition: "inline")
end
Run Code Online (Sandbox Code Playgroud)
并在/ videos /:打开浏览器(Chrome或FF),不播放视频.
如果我将相同的视频放在公共文件夹中,并像/video.mp4那样访问它,它将播放.
如果我删除了dispositon:"inline"它会下载视频,我可以从我的电脑上播放它.webm视频也是如此.
我错过了什么?这可能吗?
要流式传输视频,我们必须处理某些浏览器的请求字节范围.
send_file_with_rangegem简单的send_file方法是让send_file_with_range gem修补该方法.
在Gemfile中包含gem
# Gemfile
gem 'send_file_with_range'
Run Code Online (Sandbox Code Playgroud)
并提供以下range: true选项send_file:
def show
video = Video.find(params[:id])
send_file video.full_path, type: "video/mp4",
disposition: "inline", range: true
end
Run Code Online (Sandbox Code Playgroud)
补丁很短,值得一看.但是,不幸的是,它对我来说对Rails 4.2不起作用.
send_file手动修补受宝石的启发,手动扩展控制器非常简单:
class VideosController < ApplicationController
def show
video = Video.find(params[:id])
send_file video.full_path, type: "video/mp4",
disposition: "inline", range: true
end
private
def send_file(path, options = {})
if options[:range]
send_file_with_range(path, options)
else
super(path, options)
end
end
def send_file_with_range(path, options = {})
if File.exist?(path)
size = File.size(path)
if !request.headers["Range"]
status_code = 200 # 200 OK
offset = 0
length = File.size(path)
else
status_code = 206 # 206 Partial Content
bytes = Rack::Utils.byte_ranges(request.headers, size)[0]
offset = bytes.begin
length = bytes.end - bytes.begin
end
response.header["Accept-Ranges"] = "bytes"
response.header["Content-Range"] = "bytes #{bytes.begin}-#{bytes.end}/#{size}" if bytes
send_data IO.binread(path, length, offset), options
else
raise ActionController::MissingFile, "Cannot read file #{path}."
end
end
end
Run Code Online (Sandbox Code Playgroud)
因为,首先,我不知道之间的区别stream: true和range: true,我发现这个railscast有所帮助:
http://railscasts.com/episodes/266-http-streaming
| 归档时间: |
|
| 查看次数: |
1529 次 |
| 最近记录: |