我正在学习Ruby + Sinatra,并发现了一篇很好的帖子here,其中讨论了如何上传文件。
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
请帮忙!
答案 0 :(得分:2)
我不确定你期待你的第二个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代码和-F
选项来完成您现在正在做的事情。 multipart/form-data
与JSON的一部分用于元数据,将其他部分与原始上传文件一起使用。我可能会选择第一个选项,因为它得到了广泛的支持。
答案 1 :(得分: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
答案 2 :(得分:0)
现在我可以使用以下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)