Current section
Files
Jump to
Current section
Files
lib/remote_file_streamer.ex
defmodule RemoteFileStreamer do
@moduledoc """
RemoteFileStreamer is a micro-library to stream a remote file.
Mostly, it provides a `stream` function taking a url as an input and returns a stream out of it.
"""
@doc """
If the server hosting the resource allows it, a file a streamed from a url
## Examples
url
|> RemoteFileStream.stream
|> Enum.each(fn(chunk) -> IO.puts chunk end)
"""
@spec stream(String.t()) :: Enumerable.t()
def stream(url) do
Stream.resource(fn -> build_stream(url) end, fn resp -> read_stream(resp) end, fn _resp ->
:ok
end)
end
defp build_stream(remote_file_url) do
HTTPoison.get!(remote_file_url, [], stream_to: self(), async: :once)
end
defp read_stream(resp) do
%HTTPoison.AsyncResponse{id: ref} = resp
receive do
%HTTPoison.AsyncStatus{id: ^ref} ->
continue(resp)
%HTTPoison.AsyncHeaders{id: ^ref} ->
continue(resp)
%HTTPoison.AsyncChunk{chunk: chunk, id: ^ref} ->
_ = stream_next(resp)
{[chunk], resp}
%HTTPoison.AsyncEnd{id: ^ref} ->
{:halt, resp}
end
end
defp continue(resp) do
resp
|> stream_next
|> read_stream
end
defp stream_next(resp) do
{:ok, ^resp} = HTTPoison.stream_next(resp)
resp
end
end