【问题标题】:Elixir - Download a File (Image) from a URLElixir - 从 URL 下载文件(图像)
【发布时间】:2020-03-09 18:58:40
【问题描述】:

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

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

【问题讨论】:

    标签: elixir


    【解决方案1】:

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

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

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

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

    你去吧:)。

    这显然是可能的,即使不使用 httpoison,但你必须处理原始 TCP 连接(查看gen_tcp Erlang 模块),解析 HTTP 响应和一堆你通常不会做的事情'不想手动做。

    哎呀,忘了提到httpc Erlang 模块(包含在标准库中!),这使得这非常简单,不需要像 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)
    

    【讨论】:

    • 感谢您提及:httpc
    • 要使用 https 连接,请在 :inets 之后使用 :ssl.start
    • @denis.pelin 和 Nomad:从您个人的经历中很好奇,如果使用 HTTPC 与 HTTPoison 相比有什么显着差异?
    【解决方案2】:

    使用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 库。

    【讨论】:

    • 在我看来,这应该是公认的答案——它不使用外部库,并且以一种内存有效的方式来实现。
    • 接下来的重要说明:单引号 do 在这段代码中很重要:不知道为什么,但显然这是 Erlang 所期望的。此外,它的效果非常好。
    • 关于单引号的另一个注意事项:如果您正在使用 Elixir 字符串,只需使用 String.to_charlist 将它们转换为传递给这个库。
    【解决方案3】:

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

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-12
      • 2015-10-01
      • 2021-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多