如何在Phoenix的第一个答案here中实现流程?起初我以为我必须使用\n
和Conn.send_chunked
,但我开始意识到我会收到很多请求,而不是发送各种回复。
答案 0 :(得分:2)
如果有人感兴趣,这是我的解决方案。与视频播放器正确对话,并处理普通文件。
[range_start, range_end] =
if Enum.empty?(Conn.get_req_header(conn, "range")) do
[0, file.content_length - 1]
else
[rn] = Conn.get_req_header(conn, "range")
res = Regex.run(~r/bytes=([0-9]+)-([0-9])?/, rn)
default_end = Integer.to_string(file.content_length - 1)
{range_start, _} = res |> Enum.at(1) |> Integer.parse
{range_end, _} = res |> Enum.at(2, default_end) |> Integer.parse
[range_start, range_end]
end
content_length = range_end - range_start + 1
conn = conn
|> Conn.put_resp_content_type(file.content_type)
|> Conn.put_resp_header("content-length", Integer.to_string(content_length))
|> Conn.put_resp_header("accept-ranges", "bytes")
|> Conn.put_resp_header("content-disposition", ~s(inline; filename="#{file.filename}"))
|> Conn.put_resp_header("content-range", "bytes #{range_start}-#{range_end}/#{file.content_length}")
|> Conn.send_file(206, "#{files_path}/#{id}", range_start, content_length)
答案 1 :(得分:1)
感谢发布您的解决方案Cristian!我从来没有想过这个......否则......
对于任何像我这样的Elixir新手,遇到这种情况并且完全让上述片段工作,这是我的完整控制器方法:
def load_song(conn, params) do
filename = List.first(params["song"])
file_path = "priv/static/sounds/#{filename}"
{:ok, stats} = File.stat(file_path)
filesize = stats.size
[range_start, range_end] =
if Enum.empty?(Plug.Conn.get_req_header(conn, "range")) do
[0, filesize - 1]
else
[rn] = Plug.Conn.get_req_header(conn, "range")
res = Regex.run(~r/bytes=([0-9]+)-([0-9])?/, rn)
default_end = Integer.to_string(filesize - 2)
{range_start, _} = res |> Enum.at(1) |> Integer.parse
{range_end, _} = res |> Enum.at(2, default_end) |> Integer.parse
[range_start, range_end]
end
content_length = range_end - range_start + 2
conn
|> Plug.Conn.put_resp_content_type("audio/mpeg")
|> Plug.Conn.put_resp_header("content-length", Integer.to_string(content_length))
|> Plug.Conn.put_resp_header("accept-ranges", "bytes")
|> Plug.Conn.put_resp_header("content-disposition", ~s(inline; filename="#{filename}"))
|> Plug.Conn.put_resp_header("content-range", "bytes #{range_start}-#{range_end}/#{filesize}")
|> Plug.Conn.send_file(206, file_path, range_start, content_length)
end
我已经学会了一些基本的Elixir功能,比如混叠,这会简化这一点,而且我猜测其他一些编码选择有点不合时宜,但上面的展示工作如下a"跌入"控制器的方法。
答案 2 :(得分:1)
我为这个名为plug_range创建了一个插件,它将捕获每个范围请求并提供它们。 遵循RFC仍然是一项正在进行中的工作,但在此之前它可能会派上用场。