Rails : File upload without Carrierwave && Paperclip

The most important thing to remember with file uploads is that the rendered form’s encoding MUST be set to multipart/form-data. I guess you have that maintained.

<%= form_tag({action: :upload}, multipart: true) do %>
  <%= file_field_tag 'file' %>
<% end %>

Now in controller you will have access to IO object via params. The object in the params hash is an instance of a subclass of IO.

The object will have an original_filename attribute containing the name the file had on the user’s computer and a content_type attribute containing the MIME type of the uploaded file.

You can either move the temporary file to some dir in your public directory or simple use and throw away.

def upload
  uploaded_io = params[:file]

  # Moving the file to some safe place; as tmp files will be flushed timely
  File.open(Rails.root.join('public', 'uploads', uploaded_io.original_filename), 'wb') do |file|

for you, you can leverage the tempfile attribute in the IO object. The actual file is accessible via the tempfile accessor, though some of its interface is available directly for convenience.

So, this should work

csv_text = File.read(file.tempfile)

> uploaded_io = params[:file]
=> #<ActionDispatch::Http::UploadedFile:0x007f4154fe9a38
 @headers="Content-Disposition: form-data; name=\"file\"; filename=\"3423loadshedding.pdf\"\r\nContent-Type: application/pdf\r\n",

[2] pry(#<PostsController>)> uploaded_io.tempfile
=> #<File:/tmp/RackMultipart20160421-14883-1lv0qtq.pdf>

> uploaded_io.tempfile.class
=> Tempfile

For Error

ProductsController#upload No such file or directory @ rb_sysopen - /<path to my app>/public/uploads/X.csv 

You need to first create the folder public/uploads

$ mkdir public/uploads

Now try; the file should be moved. This is how Paperclip and Carrierwave manage uploaded files.

What does enctype=’multipart/form-data’ mean in a form

HTML forms provide three methods of encoding.

  • application/x-www-form-urlencoded (the default)
  • multipart/form-data
  • text/plain

The specifics of the formats don’t matter to most developers. The important points are:

When you are writing client-side code, all you need to know is use multipart/form-data when your form includes any <input type="file"> elements.

When you are writing server-side code: Use a prewritten form handling library (e.g. Perl’s CGI->paramor the one exposed by PHP’s $_POST superglobal) and it will take care of the differences for you. Don’t bother trying to parse the raw input received by the server.