Uploading a file in Rails
Update 2018
While everything written below still holds true, Rails 5.2 now includes active_storage
, which allows stuff like uploading directly to S3 (or other cloud storage services), image transformations, etc. You should check out the rails guide and decide for yourself what fits your needs.
While there are plenty of gems that solve file uploading pretty nicely (see https://www.ruby-toolbox.com/categories/rails_file_uploads for a list), rails has built-in helpers which make it easy to roll your own solution.
Use the file_field
-form helper in your form, and rails handles the uploading for you:
<%= form_for @person do |f| %>
<%= f.file_field :picture %>
<% end %>
You will have access in the controller to the uploaded file as follows:
uploaded_io = params[:person][:picture]
File.open(Rails.root.join('public', 'uploads', uploaded_io.original_filename), 'wb') do |file|
file.write(uploaded_io.read)
end
It depends on the complexity of what you want to achieve, but this is totally sufficient for easy file uploading/downloading tasks. This example is taken from the rails guides, you can go there for further information: http://guides.rubyonrails.org/form_helpers.html#uploading-files
How to upload a file in rails?
Usually gems/plugins are used to to handle file uploads. My favorite one, and perhaps the most ubiquitous is Paperclip.
In your view, you'll have to tell the rails form helpers that you're uploading a file like this:
<%= form_for @model, :html => { :multipart => true } do |form| %>
how to upload files in rails
If your goal is to upload a file to a directory you shouldn't have to use Carrierwave or Paperclip. Those gems have a lot of support for image processing and extra options.
I suggest you look at the Ruby file class and the open method to be more specific. http://www.ruby-doc.org/core-1.9.3/File.html#method-c-open
Something like the following should do the trick:
# "public/csv" is the directory you want to save the files in
# upload["datafile"] is the data populated by the file input tag in your html form
path = File.join("public/csv", upload["datafile"].original_filename)
File.open(path, "wb") { |f| f.write(upload["datafile"].read) }
Keep in mind, your public directory is accessible to the world. If you need to save these in a more private location, make sure the directory is only readable and writable by your app.
Also, if you are working with CSV files, be sure to read through the Ruby CSV class: http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV.html. It makes working with CSV files a breeze.
Uploading File into Server and store the path in database in Ruby on Rails
db/migrate/20110711000004_create_files.rb
class CreateFiles < ActiveRecord::Migration
def change
create_table :files do |t|
t.string :name
# If using MySQL, blobs default to 64k, so we have to give
# an explicit size to extend them
t.binary :data, :limit => 1.megabyte
end
end
end
app/controllers/upload_controller.rb
class UploadController < ApplicationController
def get
@file = File.new
end
end
app/views/upload/get.html.erb
<% form_for(:file,
url: {action: 'save'},
html: {multipart: true}) do |form| %>
Upload your file: <%= form.file_field("uploaded_file") %><br/>
<%= submit_tag("Upload file") %>
<% end %>
app/models/file.rb
class File < ActiveRecord::Base
def uploaded_file=(file_field)
self.name = base_part_of(file_field.original_filename)
self.data = file_field.read
end
def base_part_of(file_name)
File.basename(file_name).gsub(/[^\w._-]/, '')
end
end
app/controllers/upload_controller.rb
def save
@file = File.new(params[:file])
if @file.save
redirect_to(action: 'show', id: @file.id)
else
render(action: :get)
end
end
app/controllers/upload_controller.rb
def file
@file = File.find(params[:id])
send_data(@File.data,
filename: @File.name,
disposition: "inline")
end
app/controllers/upload_controller.rb
def show
@file = File.find(params[:id])
end
app/views/upload/show.html.erb
<h3><%= @file.name %></h3>
<img src="<%= url_for(:action => 'file', :id => @file.id) %>"/>
simple file upload in Rails doesn't work
This solution worked for me (reference).
Controller: Changed the saving directory from public to public/uploads. Used Rails.root to do the join of the path.
def upload
uploaded_io = params[:file]
File.open(Rails.root.join('public', 'uploads',uploaded_io.original_filename), 'wb') do |file|
file.write(uploaded_io.read)
respond_to do |format|
format.html { redirect_to(root_url, :notice => 'File was uploaded.') }
end
end
end
Form: Changed the form_for to form_tag
=form_tag({action: :upload}, multipart: true) do
= file_field_tag 'file'
= submit_tag 'Upload'
Routes:
root :to => "pages#index"
resources :pages do
collection {post :upload}
end
Ruby Rails: Upload File
It looks like params[:upload] isn't what you think it is. You forgot to set the form to be multipart. If fixing that doesn't make it work, start inspecting params to see what you're actually getting.
def uploadfile
puts params.inspect # Add this line to see what's going on
post = DataFile.save(params[:upload])
render :text => "File has been uploaded successfully"
end
Also, it's not a great "answer," but I've had good success using paperclip to handle file uploads. If you just want something that works (rather than learning how to do it yourself), check into that.
Related Topics
How to Programmatically Generate Heroku-Like Subdomain Names
Extract Links (Urls), with Nokogiri in Ruby, from a Href HTML Tags
How to Convert Array of Activerecord Models to CSV
Failed to Build Gem Native Extension When Install Redcloth-4.2.9 Install Linux
What Does ':Location => ...' and 'Head :Ok' Mean in the 'Respond_To' Format Statement
How to Call a Super Class Method
In Ruby, What Structures Can a 'Rescue' Statement Be Nested In
How to Remove All Non - Ascii Characters from a String in Ruby
How to Set Up a Sinatra App Under Apache with Passenger
How to List the Currently Available Objects in the Current Scope in Ruby
Check Whether a String Contains One of Multiple Substrings
Ruby: Create a String from Bytes
Check If User Is Active Before Allowing User to Sign in with Devise (Rails)
Activemodel::Missingattributeerror Occurs After Deploying and Then Goes Away After a While