使用Elixir和Hackney以流的形式读取数据

使用Elixir和Hackney以流的形式读取数据,elixir,Elixir,我正在使用,并且我正在尝试使用来自的指令将请求主体作为流来读取。 因为那里的代码是用Erlang编写的,所以我必须对其进行调整,使其在Elixir中工作: def read_body(max_length, client, acc) when max_length > byte_size(acc) do case :hackney.stream_body(client) do {:ok, data} -> read_body(max_length, clien

我正在使用,并且我正在尝试使用来自的指令将请求主体作为流来读取。 因为那里的代码是用Erlang编写的,所以我必须对其进行调整,使其在Elixir中工作:

  def read_body(max_length, client, acc) when max_length > byte_size(acc) do
    case :hackney.stream_body(client) do
      {:ok, data} -> read_body(max_length, client, acc <> data)
      :done -> {:ok, acc}
      {:error, reason} -> {:error, reason}
    end
  end

  def read_body(max_length, client, acc) do
    acc
  end
问题是,我希望使用上面的代码只从正文中读取前20个字节的数据,但是
acc
变量获取整个正文,当max\u length>byte\u size(acc)时,它或者不考虑保护
,或者它只是在第一次调用
:hackney.stream\u body/1
时读取所有正文


您认为如何解决此问题?

您的
read\u body/3
功能出现以下两种情况之一:

  • 正如您所提到的,正在从
    :hackney.stream\u body/1
    调用中立即返回整个正文,该调用恰好大于
    max\u length
    ,从而导致调用
    read\u body/3
    的第二个定义
  • 正文部分将作为
    read\u body/3
    递归执行返回,直到
    acc
    的大小不再小于
    max\u length
    ,这将导致调用
    read\u body/3
    的第二个定义(与1的结果相同)
  • 无论是
    :hackney.stream_body/1
    函数还是
    read_body/3
    保护程序实际上都不会基于
    最大长度限制返回正文的大小。在这两种情况下,
    acc
    大于指定的
    max_length
    ,则
    :done
    案例(或
    {:error,reason}
    案例)将永远不匹配

    为了限制返回正文的大小,一种解决方案是在
    case
    表达式中添加两个额外的保护,并删除没有保护的
    read_body/3
    的第二个定义:

    def读取主体(最大长度、参考、附件)do
    案例:hackney.stream_body(参考)do
    {:好,当字节大小(acc)>最大长度->
    读体(最大长度,参考,附件)
    {:好的,数据}当(字节大小(数据)+字节大小(acc))>最大长度->
    读取正文(最大长度,参考,acc字符串.slice(数据,0,最大长度-字节大小(acc)))
    {:好的,数据}->
    读取主体(最大长度、参考、acc数据)
    :完成->
    {:好的,acc}
    {:错误,原因}->
    {:错误,原因}
    结束
    结束
    
    另一种解决方案可能是从
    max_length
    中减去返回数据的大小,直到达到
    0
    ,然后忽略其余数据:

    def read_body(0,ref,acc)do
    案例:hackney.stream_body(参考)do
    {:好的,{}->
    读体(0,参考,附件)
    :完成->
    {:好的,acc}
    {:错误,原因}->
    {:错误,原因}
    结束
    结束
    def读取体(最大长度,参考,附件)do
    案例:hackney.stream_body(参考)do
    {:好的,>}->
    读取主体(0,参考,acc数据)
    {:好的,数据}->
    读取正文(最大长度-字节大小(数据),参考,acc数据)
    :完成->
    {:好的,acc}
    {:错误,原因}->
    {:错误,原因}
    结束
    结束
    
    这两种解决方案具有相同的结果,但显示了解决同一问题的两种不同方法

    acc = HackneyTutorial.read_body(20, client, "")                     
    # I have my own methods for retrieving the client