1

我正在学习 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

我现在该怎么办?

编辑:

第48行是这个file.write(datafile[:tempfile].read

请帮忙!

4

3 回答 3

2

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

例如,如果您有一个test.txt包含内容的文件This is a test.并且您确实请求这样:

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/form-data. 也就是说,用你的 Ruby 代码和-Fcurl 选项做你现在正在做的事情。
  • multipart/form-data与 JSON 的一部分一起用于元数据,另一部分与原始上传的文件一起使用。
  • 通过 base64 编码将文件嵌入到 JSON 中。
  • 执行某种双请求工作流,首先将元数据作为 JSON 发布,然后将文件上传到 POST 正文中。

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

于 2012-12-26T16:57:08.277 回答
1

好像你的 Ruby 代码坏了;你忘了一个end

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
于 2012-12-25T15:16:35.133 回答
0

现在我可以使用下面的带有 JSON 的 curl 命令让它工作:

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'POST 文件,如何使用 JSON 对象在服务器端检索文件?

以下不再工作。

tempfile = params[:file][:tempfile]
filename = params[:file][:filename]
dest = "#{userdir}/#{filename}"
FileUtils.cp(tempfile.path, dest) if not File.exists?(dest)
于 2012-12-27T06:25:39.013 回答