Uploading Files in Ruby on Rails

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

Ruby on rails File Upload and download

It seems your form us sending GET where it should be a POST or vice-versa. First, check your routes by running:

rake -T

and find your controller, action combination there. Check the http verb expected, and send it with your form like this:

<%= form_tag "", method: :get %>

assuming your post is happening to the same route you're in.

ruby on rails : about file upload and show file

I see at least a problem in your conditions:
alpha || beta will just evaluate as beta if alpha is "true-ish".

Try changing your conditionals to something like

['audio/mpeg', 'audio/x-mpeg', 
'audio/mp3', 'audio/x-mp3'].include?(@listing.file_content_type)

This is probably why it's giving you an image instead of playing an audio file appropriately. The way you have it, unless your file is mp4, gif, or mpegaudio, you will get an image.

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.

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.

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 and handle processing and validations - a very general overview?

This isn't a really difficult problem to solve if you are willing to change the process flow a little bit.

In the client side, the user drags and drops the files the user wants to upload.

When the user requests the upload operation to begin you can make HTTP GET requests to an API Gateway endpoint, backed with a Lambda. The Lambda can query for previous files uploaded by the client and send back a result set showing what files already exist. You then filter those out and send only what is considered new from the client to the server. This will save the user time in waiting for the upload to happen and save you time on the S3/Lambda side of not having to store duplicates or process them. This isn't a substitute for server-side validation though, you'll still want to do that. For legit clients, this will save you and them a lot of bandwidth and storage.

All the files are then uploaded (whether zipped or otherwise) to a temporary bucket location via the Shrine gem.

This works. As they enter the temp bucket, use a Lambda with an S3 event to process the files, unzip files, push any metadata needed into DynamoDb and delete the files from the temp bucket. In the temp bucket, I would place the files into a folder that is unique per request and user. I would take the user/client Id and a UUID of some kind and make that your folder name. Such as Johnathon+3b5339b8-c8db-4d5c-b678-406fcf073f4f, or encode this value into a Base64 string and make that your folder name. Store this in DynamoDb with each file uploaded into your permanent bucket with the Hash Key being the userid/clientid, a Sort Key being the full folder path + file name and an extra attribute of IsProcessed. The IsProcessed attribute will be updated by your Lambda that is processing the files and moving them to their permanent S3 bucket. If there are errors, you can put the error in this field. If it is successful then you put it in this field.

the keys for these files must somehow be returned to the client, to handle validation issues – but then how would the AWS lambda function be able to return this request to the original client side where the request was originated? Or rather,should the AWS lambda function be generated from the client side,passing in the IDs of the unzipped blobs?

The original API request to push the files to the temp S3 bucket would be able to return back to the client the folder name johnathon+3b5339b8-c8db-4d5c-b678-406fcf073f4f to the client. So let's say you made a HTTP POST to /jobs. You would return back 201 Created with a HTTP Header of Location /jobs/johnathon+3b5339b8-c8db-4d5c-b678-406fcf073f4f. Your client can then start polling /jobs/johnathon+3b5339b8-c8db-4d5c-b678-406fcf073f4f for the status of the process.

Your response back to /jobs/johnathon+3b5339b8-c8db-4d5c-b678-406fcf073f4f can return the DynamoDB records. This would include all DynamoDB records for the HashKey matching the folder name. Your client side can look at all of the objects in the result set and check the IsProcessed attribute to see if everything worked out ok, or if there were issues.

Then we need to run some validations: we want to handle the situation where there are duplicate files. We will need to check with our rails backed as to whether those files have already been uploaded.

Handle this with the Lambda that is executed by the temporary bucket. Grab the files from the temp bucket folder, handle your business logic and back-end queries then push them to their final permanent bucket.

After those validation issues are handled, then user submits the form, and all the keys are stored within the appropriate records.

All of this would happen asynchronously, starting when the user submits the form. The client side needs to be able to handle this by making HTTP GET requests to the endpoint mentioned above, checking for the status of the process. This gives you some more flexibility as you can also publish SNS messages on failures as well, such as sending an email to the clients if they upload 3,000 files and you need to spend 30 minutes processing them.

Upload Files to a particular Folder in Ruby On Rails 4

As @dharam mentioned. you can use paperclip. The working example you can find here

demo

If you want to specify folder path where the attachments should move. you need to write this in your model

has_attached_file :attachment, :path => ":rails_root/attachments/:id/:style/:basename.:extension"

After this all your attachments will be seen in attachments folder in your Application root



Related Topics



Leave a reply



Submit