In my view file submit.html.erb
, I decided to use the <form>
tag straightforwardly, instead of the form helpers included with rails. Here is the view file:
<form action = "/winter" method="post">
<input type="file" name="doc">
<p> Upload your question. </p>
<input type = "submit">
<input name="authenticity_token" type="hidden"
value="....">
</form>
Submitting this form invokes a post request on /winters
with parameters
{"doc"=>"1.docx", "authenticity_token"=>"...."}
While I expected the doc
parameter to be the file 1.docx
I uploaded, the doc
parameter continues to be the string original_filename
of file 1.docx
.
My routes.rb
file has the code
post "/winter" => "paper#submit"
while inside the submit method of paper_controller is the code:
File.write("Papers/rain.docx", params[:doc].read)
redirect_to "/paper"
And correspondingly, when I submit the aforementioned form, I go the /winters
url and get the error
undefined method 'read' for "1.docx":String
So why is the doc
parameter set as the filename rather than the file itself? This is in contrary to the docs, I suppose: [http://guides.rubyonrails.org/form_helpers.html#what-gets-uploaded]
One more point, probably relevant here, is that, there in the doc's first paragraph it says:
Depending on the size of the uploaded file it may in fact be a StringIO or an instance of File backed by a temporary file.
So, is it saying that sometimes the params[:doc]
might be a file instance, other times it might be a string? How to deal with such random behavior?
And, one more thing, what if I tried get
request instead of put
request? get
has to put the params right after the url, as a query string, right? So should then params[:doc]
be always a string? I tried using get
, and was sent to the url
http://localhost:3000/winter?doc=1.docx
(I wasn't using the authenticity token
params' hidden input then).
And of course, the same
undefined method 'read' for "1.docx":String
error occurred.
You have to use multipart/formdata encoding for file transfers to work. This is true for any web framework.
I would suggest you just use the form helpers as it will add the correct authenticity token:
<%= form_tag("/winter", multipart: true) do %>
<%= file_field_tag 'doc' %>
# ...
<% end %>
And, one more thing, what if I tried get request instead of put request? get has to put the params right after the url, as a query string, right? So should then params[:doc] be always a string? I tried using get, and was sent to the url
You cannot upload files in a GET request. They must be included in the request body of a POST/PATCH/PUT request with multipart/formdata encoding.
Files are binary - the query string which is used to pass data in GET requests is just a string containing formdata key/value pairs. Thus to pass a file in a GET request you would need to base64 encode it which inflates the file size by ~30%. Many browsers also limit the length of URIs as do some web servers to prevent DOS attacks which makes it a really bad idea.