使用 HTTParty 发送多个文件

Posted

技术标签:

【中文标题】使用 HTTParty 发送多个文件【英文标题】:Send multiple files using HTTParty 【发布时间】:2019-05-17 16:11:23 【问题描述】:

这是使用Net::HTTP::Post的代码

request = Net::HTTP::Post.new(url)
...
form_data = [
  ['attachments[]', File.open('file1.txt')],
  ['attachments[]', File.open('file2.txt')]
]
request.set_form form_data, 'multipart/form-data'
http.request(request)

现在,我正在尝试使用httparty,如下所示,但它不起作用。

body =  attachments: [ File.open('file1.txt'), File.open('file2.txt') ] 

HTTParty.post(url, body: body)

我从网络服务调用得到的响应如下:

#<HTTParty::Response:0x557d7b549f90 parsed_response="error"=>true, "error_code"=>"invalid_attachment", "error_message"=>"Attachmen
t(s) not found or invalid.", @response=#<Net::HTTPBadRequest 400 Bad Request readbody=true>, @headers="server"=>["nginx"], "date"=>[
"Mon, 20 May 2019 07:41:50 GMT"], "content-type"=>["application/json"], "content-length"=>["102"], "connection"=>["close"], "vary"=>["
Authorization"], "set-cookie"=>["c18664e1c22ce71c0c91742fbeaaa863=uv425hihrbdatsql1udrlbs9as; path=/"], "expires"=>["Thu, 19 Nov 1981
08:52:00 GMT", "-1"], "cache-control"=>["no-store, no-cache, must-revalidate", "private, must-revalidate"], "pragma"=>["no-cache", "no
-cache"], "x-ratelimit-limit"=>["60"], "x-ratelimit-remaining"=>["59"], "strict-transport-security"=>["max-age=63072000; includeSubdom
ains;"]>

它似乎无法读取文件的内容。 HTTParty 是否支持这个或者我需要使用其他一些 gem?

【问题讨论】:

你能发布完整的回溯错误吗?你确定你点击的网址有效吗? 你试过了吗,form_data = [ ['attachments[0]', File.open('file1.txt')], ['attachments[1]', File.open('file2. txt')] ] 文件是否有错误的数据或格式? 【参考方案1】:

这样的东西应该可以工作,我刚刚测试过,对我来说没问题。

HTTParty.post(url, 
              body:  attachments: [ 
                   File.read('foo.txt'), 
                   File.read('bar.txt')] )

【讨论】:

multipart 自动用作内容类型 对...我删除了该选项并进行了更新。不确定是什么问题,听起来像是服务器端的问题。 @RajkaranMishra,我尝试过这种方式,它的工作原理,您是否通过此答案解决了您的问题? 当我使用它发送图像文件时,它会显示不支持的媒体文件。【参考方案2】:

使用 HTTParty,您可以以相同的方式将 IO/Files 作为参数传递(如果参数中有文件,则 multipart 会自动设置为 true)。

但请记住,文件应该在上传后关闭,否则您可能会在 GC 收集之前用完文件描述符:

files = ['file1.txt', 'file2.txt'].map|fname| File.open(fname) 
begin
  HTTParty.post(url, body:  attachments: files )
ensure
  files.each(&:close)
end

如果 net/http 变体有效(并且实际上与您的代码相同),那应该对您有用。

其他需要注意的是通过文件名检测内容类型 - 因为文件上传由文件名、内容类型和数据本身组成。 您收到的带有“invalid_attachment”的错误 400 表明它更可能与服务器端的内容类型或其他验证有关(因此请确保您使用相同的文件进行测试,并且除了 http lib 之外没有其他任何更改),还请检查 httparty成为最新版本

【讨论】:

【参考方案3】:

我编写了一个测试程序,它使用Net::HTTPHTTParty 发送相同的多部分请求。然后它比较并打印请求字符串,以便我们可以比较它们。两个请求之间唯一的实质性区别是 HTTParty 尝试猜测并设置 Content-Type 标头(例如,text/plain 用于名为 file1.txt 的文件),而 Net::HTTP 始终使用 @ 987654326@.

HTTParty 确实会读取文件并在请求中发送它们。因此,我建议您调查一下服务器是否由于Content-Type 而返回错误(可能不支持您的特定请求中的内容类型)。

供您参考,这里是test program and specific results。

【讨论】:

以上是关于使用 HTTParty 发送多个文件的主要内容,如果未能解决你的问题,请参考以下文章

用HTTParty在body中发送带有数组的POST请求。

Ruby HTTParty - 获取重定向的 URL

如何关闭 HTTParty 帖子正文中的 URI 编码?

Ruby——httparty使用代理

使用 HTTParty 解析 HTTP 标头“set-cookie”

将 curl 命令转换为 httparty