Ruby Ruby post 发送 form-data 数据

glorySpring · 2015年06月05日 · 最后由 bolasblack 回复于 2015年06月08日 · 9105 次阅读

正在做一个项目,对方的 API 使用 Java maven restful service 写的。 对方要求发送 form-data 类型数据。 尝试多次后,每次都返回

415 Unsupported Media Type

这个错误,虽然知道什么错误,但是,不知道该怎么发送数据了。 对方使用 Java 测试,我看对方测试的源代码,使用的是

MultipartEntityBuilder

去填写数据发送的。 我的做法是


_url = "http://localhost:8080/hiwitservice/bio/test"

uri = URI.parse("http://localhost:8080")
http = Net::HTTP.new(uri.host, uri.port)

request = Net::HTTP::Post.new("/hiwitservice/bio/test")
request.add_field('Content-Type', 'application/json')
request.add_field('enctype', 'multipart/form-data')
request.body = {'apiId' => 'username', 'apiKey' => 'key'}.to_json

http.set_debug_output($stdout)

response = http.request(request)

但是,还是一样的错误。

输出结果

#<IO:0x007ff9998c6550>
opening connection to localhost:8080...
opened
<- "POST /hiwitservice/bio/test HTTP/1.1\r\nAccept-Encoding: gzip;q=1.0,deflate;q=0.6,identity;q=0.3\r\nAccept: */*\r\nUser-Agent:
 Ruby\r\nEnctype: multipart/form-data\r\nConnection: close\r\nHost: localhost:8080\r\nContent-Length: 35\r\nContent-Type: applicat
ion/x-www-form-urlencoded\r\n\r\n"
<- "{\"apiId\":\"username\",\"apiKey\":\"key\"}"
-> "HTTP/1.1 415 Unsupported Media Type\r\n"
-> "Server: Apache-Coyote/1.1\r\n"
-> "Date: Thu, 04 Jun 2015 20:11:38 GMT\r\n"
-> "Content-Length: 0\r\n"
-> "Connection: close\r\n"
-> "\r\n"
reading 0 bytes...
-> ""
read 0 bytes
Conn close

有人有类似的经验吗?求指教。。。。无头头绪了。

补充,之后再次尝试,直接写 HTML 页面表单。

<form action="http://www.test.com/v1/demo/test" method="post" enctype="multipart/form-data">
    <input type="text" value="123" name="appId"/>
    <input type="text" value="456" name="appKey" />
    <input type="submit" value="提交" />
</form>

这个样子是在页面正确显示了 call ok 的字样。

再求指点。。。

multipart/form-data是上传文件用的,你确定form-data不是单纯的用 html 的 form 来放入数据后直接 post 请求么?

#1 楼 @ywjno 是的 是用 ruby NET::HTTP 来完成这个操作,不是在网页上写一个 form 表单。我郁闷的地方也在这里,为什么会有这么奇葩的接口。

form-data 不一定指 multipart/form-data,应该指的就是普通的 POST form。

uri = URI('http://www.example.com/search.cgi')
res = Net::HTTP.post_form(uri, 'q' => 'ruby', 'max' => '50')
puts res.body

http://ruby-doc.org/stdlib-2.2.2/libdoc/net/http/rdoc/Net/HTTP.html#class-Net::HTTP-label-POST

这可不奇葩。

4 楼 已删除

#3 楼 @rei 恩,这个试过了,还是一样的错误 415 类型错误。另外他需要的类型就是

multipart/form-data

我看过对方的源代码,这个,让我很纠结。

#3 楼 @rei 哦,对了,我直接写了一个 form 表单,在 HTML 页面直接提交,竟然成功了。。

#5 楼 @glorySpring 那么用一些包装好的库吧,标准库的 Net::HTTP 不支持 multipart

https://github.com/rest-client/rest-client#multipart

#6 楼 @glorySpring 这个 form 不是 multipart 吗?

顶楼这里是错误的:

request.body = {'apiId' => 'username', 'apiKey' => 'key'}.to_json

塞了个 json 进去,对不上 enctype,用浏览器看看 HTML 表单提交的头和 body 是什么。

#7 楼 @rei 恩 这些库,我大部分都尝试了 大概有

multipart
multiparty
multipart-post
multipart_body

但是。。。结果还是 415。再不行,就只能让对方改接口了。。现在再重新试一下。谢了,这么晚,还回答问题。

#8 楼 @rei ok,我再试试。如果你想测试的话,他的测试地址是 http://ws.biovip.cc:8080/hiwitservice/v1/test 。要传的值 只有两个 appId 跟 appKey. 嘿。。

#9 楼 @glorySpring 别自己设置头了,看 7 楼链接。

RestClient.post '/data', {:foo => 'bar', :multipart => true}

#11 楼 @rei 你是我的吉祥物,OMG,之前一直测试不成功,刚刚我测试了一下竟然成功了。。兴奋中。。。谢谢谢谢。。。。

其实它的接口说的挺清楚的,就是 Content-Type 不对,你自己发起请求的时候设置了这个头为 application/json ,所以接口认为你不是 post 了一个表单,就告诉你 415 不支持这种请求体的数据格式。当然普通表单的 Content-Typeapplication/x-www-form-urlencoded ,不是 multipart/form-data ,也是不对的 Orz,在普通浏览器里只有附带文件的时候 Content-Type 才会变成 multipart/form-data ,我怀疑 Net::HTTP 本身的逻辑也是这样子的;也不建议你自己把 Content-Type 设置为 multipart/form-data ,因为其实它的格式是这样子的:

Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA

------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="text"

title
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="file"; filename="chrome.png"
Content-Type: image/png

PNG ... content of chrome.png ...
------WebKitFormBoundaryrGKCBY7qhFd3TrwA--

所以当然 @rei 的方案应该是比较好的。

以及,这个接口确实是奇葩接口,你不用觉得沮丧。原因就是我上面说的,如果真的是要求以 form 形式提交的话,不支持 application/x-www-form-urlencoded 是不对的。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号