POST error with Sinatra with JSON

I'm learning Ruby + Sinatra, and found a good post here which talks about how to upload files.

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

I can use the following cURL command to upload files fine.

curl -v -F "data=@/Users/me/Desktop/test.pdf"  http://localhost:4567/upload/test.pdf

But now I had decided to use JSON to handle all incoming/outgoing responses. I tried this, but it didn't seem to work.

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'

I also received an error like this:

NoMethodError at /upload/test.pdf
undefined method `get' for #<WebTest:0x101374dd8>
file: web.rb location: POST /upload/:filename line: 48

What should I do now?

Edited:

Line 48 is this file.write(datafile[:tempfile].read

Please help!

Answers


I'm not sure what you're expecting your second curl command to do, but I'm pretty sure it's not doing what you want. If you give more than one --data or -d parameters to curl, their values will be joined together, separated by &.

For example, if you have a file test.txt with contents This is a test. and you do request like this:

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'

This is what the request looks like:

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.

The request body is not valid JSON. It's not valid URL-encoded form data or multi-part form data either.

It's not obvious how to combine JSON requests with file uploads. Here are some options:

  • Just use multipart/form-data. That is, do what you're doing right now with your Ruby code and -F option to curl.
  • Use multipart/form-data with one part of JSON for metadata and other part with the raw uploaded file.
  • Embed the file into JSON by base64-encoding it.
  • Do some kind of two-request workflow where first you post the metadata as JSON and then you upload the file in the POST body.

I'd probably go with the first option, because it's so widely supported.


Need Your Help

QTableView does not refresh foreign keys?

c++ qt qtableview qt4.7 qsqltablemodel

I have a QMainWindow with two QTableViewson it. Each QTableView has its own QSqlRelationalTableModel. I am using OnManualSubmit as the edit strategy for both models. Both models hit the same dat...

How to initialize handlers from separated threads?

android handler

I am coding an application where a remote service has to run at all time and to perform these taks :

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.