我只是想通过 POST 将图像上传到服务器。这个任务听起来很简单,但在 Ruby 中似乎没有简单的解决方案。
在我的应用程序中,我对大多数事情都使用WWW::Mechanize,所以我也想用它来做这件事,并且有这样的来源:
f = File.new(filename, File::RDWR)
reply = agent.post(
'http://rest-test.heroku.com',
{
:pict => f,
:function => 'picture2',
:username => @username,
:password => @password,
:pict_to => 0,
:pict_type => 0
}
)
f.close
这会在服务器上产生一个完全可以垃圾的文件,看起来到处乱七八糟:
我的下一步是将 WWW::Mechanize 降级到 0.8.5 版。这一直有效,直到我尝试运行它,它失败并出现“在 hpricot_scan.so 中找不到模块”之类的错误。使用 Dependency Walker 工具,我可以发现 hpricot_scan.so 需要 msvcrt-ruby18.dll。然而,在我将那个 .dll 放入我的 Ruby/bin 文件夹之后,它给了我一个空的错误框,我无法进一步调试。所以这里的问题是 Mechanize 0.8.5 依赖于 Hpricot 而不是 Nokogiri(它完美地工作)。
下一个想法是使用不同的 gem,所以我尝试使用 Net::HTTP。经过短暂的研究,我发现 Net::HTTP 中没有对多部分表单的原生支持,相反,您必须为您构建一个编码等的类。我能找到的最有帮助的是 Stanislav Vitvitskiy 的 Multipart-class。到目前为止,这个类看起来不错,但它并没有做我需要的,因为我不想只发布文件,我也想发布普通数据,而这在他的课程中是不可能的。
我最后一次尝试是使用RestClient。这看起来很有希望,因为已经有关于如何上传文件的示例。但是我无法将表单作为多部分发布。
f = File.new(filename, File::RDWR)
reply = RestClient.post(
'http://rest-test.heroku.com',
:pict => f,
:function => 'picture2',
:username => @username,
:password => @password,
:pict_to => 0,
:pict_type => 0
)
f.close
我正在使用http://rest-test.heroku.com,如果发送正确,它会发回调试请求,我总是会得到这个:
使用 101 字节有效负载发布 http://rest-test.heroku.com/, 内容类型 application/x-www-form-urlencoded { "pict" => "#<文件:0x30d30c4>", "用户名" => "s1kx", "pict_to" => "0", “功能”=>“图片2”, "pict_type" => "0", “密码” => “密码” }
这清楚地表明它不是multipart/form-data
用作 content-type 而是用作 standard application/x-www-form-urlencoded
,尽管它肯定认为那pict
是一个文件。
如何在不实现整个编码和数据对齐的情况下将 Ruby 中的文件上传到多部分表单?