user1967829
user1967829

Reputation: 11

curl to upload file on Ruby on Rails application

I'm trying to use curl to upload a file to my small Ruby on Rails application.

Here is the insert.html.haml

= form_for :my_result, :url=>{:action=> 'save'}, :html => {:multipart=>true} do |f|
  = f.file_field :myfile
  = submit_tag 'submit'

The "save" action will be invoked when the form is submitted. But the RoR action to view the form is the "insert" action.

I can view the "insert" form with a browser and then submit my file with no problem.

But I need to submit the file using curl.
When I do a curl -F [email protected] -F commit="submit" URL/insert, I only get back the "insert" form in HTML. It doesn't seem to invoke the actual "save" action.

Started POST "/my_results/insert" for 10.15.120.173 at 2013-01-10 10:53:22 -0800
...
Rendered my_results/insert.html.haml within layouts/application (2.9ms)  

I'm new to RoR and curl. I'd appreciate any help.

Thanks!

Upvotes: 1

Views: 1361

Answers (2)

Zajn
Zajn

Reputation: 4088

I'm just taking a guess here, but your POST probably isn't making it through due to Rails requiring a csrf authenticity token, which isn't being sent with your curl request.

In the console where you see the result of your POST there is probably a line that says something along the lines of WARNING: Cannot verify authenticity token.

When you create a form using a Rails helper such as form_for, Rails automatically creates a hidden field with a generated csrf token for its value. That way, when the form submits, if the token coming in with the form and the token that Rails is expecting don't match, the request will fail.

You can read up on how to use curl with Rails here.

Here is a link to the Wikipedia article on Cross Site Request Forgery.

Also, please let me know if this is at all relevant to your issue. I'm just assuming that's the cause since I've tried POSTing with curl before and had the same problem

Upvotes: 2

user1003545
user1003545

Reputation: 2128

To upload the file, you must mimic the request that happens when the form is submitted.
The form's action is defined as

:url=>{:action=> 'save'}

which transaltes to

<form action="/save" method="POST">

So you should POST to /save

Second point, Rails automatically prefixes the fields names with the name of the object that is passed to form_for. If you look at the HTML source of /insert, the file input looks like

<input name="my_result[myfile]" type="file" />

This explains the the structure of the params hash :

{
  "my_result" => {
    "my_file" => [the file]
  }
}

which allows to access the form fields values under params[:my_result]

In summary : POST to /save and name the field my_result[my_file] :

curl -F my_result[my_file][email protected] URL/save

Upvotes: 3

Related Questions