Ruby 带JSON的Sinatra POST错误

Ruby 带JSON的Sinatra POST错误,ruby,json,post,curl,sinatra,Ruby,Json,Post,Curl,Sinatra,我正在学习Ruby+Sinatra,发现了一篇关于如何上传文件的好帖子 post '/upload/:filename' do userdir = "./upload" FileUtils.mkdir_p(userdir) unless File.exists?(userdir) filename = File.join(userdir, params[:filename]) datafile = params[:data] File.open(filename, 'wb')

我正在学习Ruby+Sinatra,发现了一篇关于如何上传文件的好帖子

post '/upload/:filename' do
  userdir = "./upload"
  FileUtils.mkdir_p(userdir) unless File.exists?(userdir)
  filename = File.join(userdir, params[:filename])
  datafile = params[:data]
  File.open(filename, 'wb') do |file|
    file.write(datafile[:tempfile].read)
  end
end
我可以使用下面的cURL命令来上传文件

curl -v -F "data=@/Users/me/Desktop/test.pdf"  http://localhost:4567/upload/test.pdf
但现在我决定使用JSON来处理所有传入/传出的响应。我试过这个,但似乎不起作用

curl -i -X POST -H Accept:application/json -H Content-Type:application/json -d '{file:{filename:"test.pdf",md5sum:"ab3d2f"}}'  --data-binary @/Users/me/Desktop/test.pdf 'http://localhost:4567/upload/test.pdf'
我还收到了如下错误:

NoMethodError at /upload/test.pdf
undefined method `get' for #<WebTest:0x101374dd8>
file: web.rb location: POST /upload/:filename line: 48
NoMethodError at/upload/test.pdf
未定义的方法“get”#
文件:web.rb位置:POST/upload/:文件名行:48
我现在该怎么办

编辑:

第48行是文件。写入(数据文件[:tempfile]。读取


请帮帮我!

你的Ruby代码好像坏了;你忘记了一个
结尾

post '/upload/:filename' do
  userdir = "./upload"
  FileUtils.mkdir_p(userdir) unless File.exists?(userdir)
  filename = File.join(userdir, params[:filename])
  datafile = params[:data]
  File.open(filename, 'wb') do |file|
    file.write(datafile[:tempfile].read)
  end
end

我不确定您希望第二个curl命令做什么,但我很确定它没有做您想要做的事情。如果您为curl提供多个
--data
-d
参数,它们的值将连接在一起,由
&
分隔

例如,如果您有一个内容为
的文件
test.txt
,则这是一个测试。
并且您的请求如下:

curl -i -X POST -H Accept:application/json -H Content-Type:application/json \
    -d '{file:{filename:"test.txt",md5sum:"ab3d2f"}}'                  \
    --data-binary @test.txt 'http://localhost:4567/upload/test.txt'
这是请求的外观:

POST /upload/test.txt HTTP/1.1
User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8r zlib/1.2.5
Host: localhost:4567
Accept:application/json
Content-Type:application/json
Content-Length: 61

{file:{filename:"test.txt",md5sum:"ab3d2f"}}&This is a test.
请求正文不是有效的JSON。它也不是有效的URL编码表单数据或多部分表单数据

如何将JSON请求与文件上载结合起来并不明显。以下是一些选项:

  • 只需使用
    multipart/formdata
    。也就是说,使用Ruby代码和
    -F
    选项即可完成当前的工作
  • 使用
    multipart/form data
    将JSON的一部分用于元数据,另一部分用于原始上传文件
  • 通过base64编码将文件嵌入JSON
  • 执行某种双请求工作流,首先将元数据发布为JSON,然后将文件上传到post正文中

我可能会选择第一个选项,因为它得到了广泛的支持。

现在我可以使用下面的curl命令和JSON来实现它:

curl -v -F 'json=[ {"filename": "@/Users/me/Desktop/test.pdf", "md5sum": "1496f9b6f42b7ed8260eadeb158c33f4", type": "generic"}, {"filename": "@/Users/me/Desktop/test2.pdf", "md5sum": "1496f9b6f42b7ed8260eadeb158c33f4", type": "generic"} ]' http://localhost:4567/upload
但是,由于我没有使用
-F'file=@/Users/me/Desktop/test.pdf'
发布我的文件,因此如何使用JSON对象在服务器端检索文件

下面的命令已不起作用

tempfile = params[:file][:tempfile]
filename = params[:file][:filename]
dest = "#{userdir}/#{filename}"
FileUtils.cp(tempfile.path, dest) if not File.exists?(dest)

你需要调试。首先,我要确定哪一行是第48行。根据Sinatra的说法,这肯定是它在POST中使用“路由”的方式。除非我在这里遗漏了什么。我为什么要关心“获取”这里因为我只需要构造一个POST方法。并且只会使用POST方法。谢谢!我在这里寻求帮助,但我可能没有一个好问题,但我肯定在寻找答案或一些建议。我对Sinatra和Ruby不熟悉,并且总是渴望学习。我只是有一些设计问题很难说清楚。因为没有一种方法做事情,这就是为什么我需要向你们学习。我仍然不知道为什么会有错误。是的。我一直使用warn/puts进行调试。我确实有,但只是没有正确地复制和粘贴。仍然无法在出现上述错误的情况下运行。谢谢!这是一个有用的答案!我使用了第一个选项,但它只支持u正在加载1个二进制文件。如果我还想发布文件和JSON内容(其中包括该文件的MD5sum),如何发布?我还没有在网上看到这样的示例。其他数据可以使用“表单字段”。
curl-F'MD5sum=ab3d2f
-F'data=@test.pdf'http://...`然后使用
params[:md5sum]访问它
在Ruby中。您也可以这样发布JSON对象。
curl-F'JSON={file:{filename:“test.txt”,md5sum:“ab3d2f”}“…
然后用Ruby解码。谢谢!但我如何使用JSON对象方式传输嵌入的文件?基本上,您必须对文件进行base64编码,或者将其转换为JSON安全格式,以便将其作为字符串放入其中。单靠curl是无法做到这一点的。如果您不使用“-F”文件=@test.pdf”,则该文件不包括在内我正在考虑在POST请求中传递多个文件。我们还有什么其他方法可以做到这一点?@xbeta答案是答案,问题是问题。这应该是问题的更新,或者这里的额外信息应该在新问题中。还有“现在我可以让它工作了”是没有意义的。请尝试
警告params.keys。检查
并查看您现在接收到的内容,因为在我看来,您现在正在发送一个散列数组,像以前那样通过键访问将不起作用。我已经声明我的新cURL命令已经起作用了。可能是因为我在开始时没有正确的语法。因此,现在一切正常。谢谢你的关心。我仍然想知道我们是否可以在POST请求中传递多个文件。我来这里是为了学习,所以我可能没有适当的条件当场提问,但我想我会鼓励人们学习,并宽恕新手。