3

我正在尝试使用 HTTPClient for Ruby 制作多部分流式传输帖子。我遇到了两个问题。

问题1:首先,如果我尝试通过文档中描述的方式进行正常发布;我通过 httpbin.org 将其返回,我看到这种情况发生了:

代码

        File.open(path_to_my_file) do |file|
          body = [{ 'Content-Type' => 'application/atom+xml; charset=UTF-8',
                    :content => '<entry>...</entry>' },
                  { 'Content-Type' => 'video/mp4',
                    'Content-Transfer-Encoding' => 'binary',
                    :content => file }]
          res = @http_client.post('http://httpbin.org/post', body: body)
          response = res
          puts res.body

结果

{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "{\"Content-Type\"=>\"application/atom+xml; charset=UTF-8\", :content=>\"<entry>...</entry>\"}": "", 
    "{\"Content-Type\"=>\"video/mp4\", \"Content-Transfer-Encoding\"=>\"binary\", :content=>#<File:{{path_to_file}}>}": ""
  }, 
  "headers": {
    "Accept": "*/*", 
    "Content-Length": "322", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Date": "Mon, 20 May 2019 06:43:17 GMT", 
    "Host": "httpbin.org", 
    "User-Agent": "HTTPClient/1.0 (2.8.3, ruby 2.6.0 (2018-12-25))"
  }, 
  "json": null, 
  "origin": "IP, IP", 
  "url": "https://httpbin.org/post"
}

如您所见,我看不到文件的内容,而只能看到包含文件 URI 的标识符;因此,我不知道如何修复它,以便我可以查看并返回内容。据我所知,它看起来像是试图将 File 对象视为一个字符串,这当然不是我想要的。

问题2: 每当我动态创建主体时,即;使用我的代码中设置的对象动态创建哈希数组,我尝试异步发送它(我相信这是让它在 Ruby 的 HTTPClient 中流式传输的正确方法,尽管我不完全确定)它发送整个身体作为数据,不再作为表单或标题。

代码

        request_body = []
        body.files.each do |k, v|
          request_body.push( { 'Content-Type' => v.content_type, :content => v.content })
        end
        body.values.each { |k, v| request_body << { k.to_sym => v }}

        #This creates the array correctly, although I just wanted to show how it was generated

        connection = @http_client.send(method + '_async', uri, body: request_body, header: headers)

        response = connection.pop
        # Starts reading result here

回复

  "args": {}, 
  "data": "%7B%22Content-Type%22%3D%3E%22video%2Fmp4%22%2C+%3Acontent%3D%3E%23%3CFile%3A%2Fhome%2Fuser%2Ffiles%2file.mp4%3E%7D=&%7B%3Avalue%3D%3E%22hello+world%22%7D=", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Content-Length": "247", 
    "Content-Type": "application/json", 
    "Date": "Mon, 20 May 2019 06:44:11 GMT", 
    "Host": "httpbin.org", 
    "User-Agent": "HTTPClient/1.0 (2.8.3, ruby 2.6.0 (2018-12-25))", 
    "ApplicationIdentifier": "identifier"
  }, 
  "json": null, 
  "origin": "IP, IP", 
  "url": "https://httpbin.org/post"
}

如您所见,它将所有内容都放入数据中,老实说,我不知道如何让它以表单而不是数据的形式发送带有正文的帖子。我将文件作为 File 对象发送到这里。我尝试将其作为普通帖子而不是 post_async 发送,但它似乎不起作用。

有没有人遇到过这些问题并且知道我应该如何解决这些问题?(或者你能看到我哪里出错了,这样我至少可以尝试更进一步)

提前致谢

4

1 回答 1

1

关于您的第一个问题,文档似乎不正确。我进行了一些测试,内容类型似乎是 application/x-www-form-urlencoded。您需要明确设置内容类型:

body: body, header: {'Content-Type': 'multipart/form-data; boundary=ABC'}

但这还不够。您还需要手动设置内容处置。例如:

      body = [{ 'Content-Type' => 'application/atom+xml; charset=UTF-8',
                'Content-Disposition' => 'form-data; name="name1"',
                :content => '<entry>...</entry>' },
              { 'Content-Type' => 'video/mp4',
                'Content-Disposition' => 'form-data; name="file"; filename="myfile.pdf"',
                'Content-Transfer-Encoding' => 'binary',
                :content => file }]

这样,httpbin 会报告一个文件和一个表单参数。

您的第二个问题与此有关。您的文件和值都需要设置内容处置。例如(又快又脏,风格可能会更好):

files.each do |k, v|
    request_body << { 'Content-Type' => v.content_type, :content => v.content, 'Content-Disposition' => 'form-data; name="' + k + '"; filename="' + v.filename + '"' }
end
values.each { |k, v| request_body << { :content => v, 'Content-Disposition' => 'form-data; name="' + k + '"' }}

请注意,您应该转义名称或文件名中的任何 "。

于 2019-05-20T13:29:37.720 回答