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

Elixir - Download a File (Image) from a URL

从 URL 下载 file/image 的代码在 Elixir 中是什么样子的?

Google 搜索似乎带回了如何下载 Elixir 本身。

看看 httpoison,Elixir 的 HTTP 客户端。您可以向指向图像(或文件,无关紧要)的 url 发出 GET 请求:

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

HTTPoison.get!/1 returns 一个 HTTPoison.Response 结构;我匹配该结构以获得响应的主体。现在 body 变量包含图像数据(只是一个二进制文件);您可以将其写入文件:

File.write!("/tmp/image.png", body)

好了 :).

即使不使用 httppoison,这显然也是可能的,但是您将不得不处理原始 TCP 连接(查看 gen_tcp Erlang 模块)、HTTP 响应的解析和一堆您通常不想手动执行的操作。

糟糕,忘了提到 httpc Erlang 模块(包含在 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)

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

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

我创建了 download 长生不老药包来绕过这些缺点。

它的语法很好并且经过了良好的测试。只需输入

Download.from(url, [path: "/where/to/save", max_file_size: integer_in_bytes])

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

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

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

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