Hi!
I have a Downloader module that GETs files given a URL, using Req. It has a timeout option but I would like to abort the download when it exceeds a given maximum size, so I don’t have to wait until the file has been completely downloaded to check the final size.
I think that can be done using Req’s streaming capabilities but I’m not being able to get it working. Can anyone help with this? This is my module so far:
defmodule Utils.Downloader do
require Logger
@default_receive_timeout_ms 20_000
def download(url, opts \\ []) do
Logger.debug("[#{__MODULE__}] downloading...")
with {:ok, req_client} <- prepare_req_client(opts),
{:ok, %Req.Response{status: 200, body: body, headers: headers}} <-
Req.get(req_client, url: url),
{:ok, content_type} <- get_content_type(headers) do
Logger.debug("[#{__MODULE__}] finished downloading...")
{:ok, %{content_type: content_type, data: body}}
else
{:error, :cant_get_content_type} ->
{:error, :cant_get_content_type}
%Req.Response{status: status} when status != 200 ->
{:erorr, :cant_download_image}
end
end
defp get_content_type(headers) do
headers
|> Enum.find(fn {key, _} -> String.downcase(key) == "content-type" end)
|> case do
{_, value} when is_list(value) -> {:ok, hd(value)}
{_, value} when is_binary(value) -> {:ok, value}
nil -> {:error, :cant_get_content_type}
end
end
defp prepare_req_client(opts \\ []) do
receive_timeout_ms = opts[:receive_timeout_ms] || @default_receive_timeout_ms
client = Req.new(receive_timeout: receive_timeout_ms)
{:ok, client}
end
end




















