Elixir - 从URL下载文件(图像)

Bud*_*Joe 21 elixir

从URL下载文件/图像的代码在Elixir中是什么样的?

谷歌搜索似乎带回了如何下载Elixir本身.

wha*_*ide 47

看看httpoison,Elixir的HTTP客户端.您只需GET向指向图像(或文件,无关紧要)的网址发出请求:

%HTTPoison.Response{body: body} = HTTPoison.get!("http://example.com/img.png")
Run Code Online (Sandbox Code Playgroud)

HTTPoison.get!/1返回一个HTTPoison.Response结构; 我在该结构上匹配以获得响应的主体.现在body变量包含图像数据(只是二进制); 你可以把它写到一个文件:

File.write!("/tmp/image.png", body)
Run Code Online (Sandbox Code Playgroud)

然后你去:).

即使不使用httpoison,这显然也是可能的,但您必须处理原始TCP连接(查看gen_tcpErlang模块),解析HTTP响应以及一些您通常不想手动执行的操作.

哎呀,忘了提到httpcErlang模块(包含在stdlib中!),这使得这非常简单,不需要像HTTPoison那样的依赖:

Application.ensure_all_started :inets

{:ok, resp} = :httpc.request(:get, {'http://example.com/my_image.jpg', []}, [], [body_format: :binary])
{{_, 200, 'OK'}, _headers, body} = resp

File.write!("/tmp/my_image.jpg", body)
Run Code Online (Sandbox Code Playgroud)

  • 谢谢你提到`:httpc`! (3认同)
  • 要使用https连接,请在`:inets`之后使用`:ssl.start` (3认同)

dev*_*fix 10

使用httpc将 URL 直接流式传输到文件:

:inets.start()
:ssl.start() 

{:ok, :saved_to_file} = :httpc.request(:get, {'https://elixir-lang.org/images/logo/logo.png', []}, [], [stream: '/tmp/elixir'])                     
Run Code Online (Sandbox Code Playgroud)

我下载了一个 183MB 的文件,观察者显示内存使用从未超过 25MB。注意单引号字符串!我们不能将 Elixir 字符串传递给这个 Erlang 库。

  • 在我看来,这应该是公认的答案 - 它不使用外部库,并且以内存有效的方式进行。 (4认同)

asi*_*niy 7

@whatyouhide 提供的下载方法有效但有缺点:

  • 整个响应正在加载到 RAM,然后才会转到File.write/1. 您必须选择异步 HTTPoison 请求来避免高内存消耗。
  • 要下载的文件大小没有限制。如果您处理用户输入,然后尝试下载用户提供的任何文件,则您的服务器可能会关闭以下载 1TB 大小的文件。

我创建了下载elixir 包来绕过这些缺点。

它有很好的语法和经过充分测试。只需输入

Download.from(url, [path: "/where/to/save", max_file_size: integer_in_bytes])
Run Code Online (Sandbox Code Playgroud)