I'm building an app where users can upload csv files to load data onto our platform. I have a form that lets a user upload a file and a method that saves the file in a specified folder. I want to append the user_id to the filename. How would I do that?
my form:
<%= form_tag import_listings_path, multipart: true do %>
<%= file_field_tag :my_file %>
<%= hidden_field_tag :user_id, current_user.id %>
<%= submit_tag "Import CSV" %>
<% end %>
my controller method:
def import
tmp = params[:my_file].tempfile
file = File.join("public", params[:my_file].original_filename)
FileUtils.cp tmp.path, file
end
For example, if a user uploads test.csv and their user_id is 20. I want the new filename to be test20.csv
A bit ugly but this should do the job... basically extracting the file extension (obtaining the last string after the '.'), appending the user id and adding the extension back:
x = params[:my_file].original_filename.split('.')
x[x.length - 2] += params[:user_id]
file = File.join("public", x.join('.'))
Related
I'm trying to upload a CSV file(without headers) to a form in Rails, and then change my database based on that file's contents.
Now, the problem I'm having is that I know my routes must be correct, because I'm able to get to the correct method...but, my #imported variable is saying it is nil even when I upload a file.
Is there any help I can get for this? This will be my first file upload in rails, so we can cross this milestone together...
Here is the form in my view, mapped to the #ship action:
<%= form_for #import, :url => {:action => "ship", :controller => "imports"} do |f| %>
<%= f.file_field :import %>
<%= f.submit %>
<% end %>
And here is the corresponding method in my controller:
def ship
#import = CSV.read(params[:file])
#import.each do |i|
Product.ship(#import[i][0]) #I believe the #read method imports
end #CSV files as an array of arrays
redirect_to "/" #But I have yet to get past the
end #first line, so I'm unsure
Sergio Tulentsev is right. You need to use params[:import][:import]. The first import being the name of your resource (comes from form_for #import, the second import being the field name (coming from f.file_field :import).
More info at http://guides.rubyonrails.org/form_helpers.html#uploading-files
I am using Carrierwave for file uploading and have got the following form, which allows me to submit several files:
<%= form_tag load_patterns_contacts_path, multipart: true, multiple: true do %>
<%= file_field_tag 'qqfile[]', id: "upload_pattern", multiple: true %>
<%= submit_tag "Load", id: "save_pattern", :class => 'btn btn-primary btn-success', multiple: true%>
<% end %>
Here is the code in my controller, which load submited files to the server:
#uploader = EmailPatternsUploader.new
params[:qqfile].each do |p|
tempfile = open(p.original_filename)
puts tempfile
#uploader.store!(tempfile)
end
redirect_to contacts_path
flash[:success] = "Uploaded successfully."
It works fine, if filename looks like "text.xlsx", "image.jpg" etc. But if it is contains special symbols like "_partial.html.erb" then I have got Errno:ENOENT (No such file or directory - _partial.html.erb)
I have tried to add
CarrierWave::SanitizedFile.sanitize_regexp = /[^[:word:]\.\_\-\+]/
in my carrierwave.rb initializer, but it gives no result.
Thanks in advance for help!
UPDATE:
I have understood, that the problem not in special symbol "_", but in the fact, that samples I am trying to upload contains two dots ("."). I think I need to modify regular expression in order to avoid two dots
UPDATE:
I am sorry for the last comments. I have understood, that the matter not in special symbols at all and not in a name of file. The problem that i can upload files only from {Rails.root} path. If I choose another directory, I have got aforementioned error and cannot upload a file. How can I configure Carrierwave path directory?
Finally find an answer on my question.
The error was in these strings of code:
params[:qqfile].each do |p|
tempfile = open(p.original_filename)
puts tempfile
#uploader.store!(tempfile)
end
I have understood, that I need to pass an object ActionDispatch::Http::UploadedFile in Carrierwave store! method. Thats why the mentioned above code shall be the following:
params[:qqfile].each do |p|
puts p.original_filename
puts p
#uploader.store!(p)
end
==================================================================================
Hope someone find this solution for multiple file uploading with Carrierwave and without JQuery useful.
1) Create an uploader, using Carrierwave.
rails g uploader EmailPatterns
2) Create a custom action for your controller (watch Railscast#35 and Railscast#38 to make it clear) and put there something like this (load_patterns in my case):
def load_patterns
#uploader = EmailPatternsUploader.new
params[:qqfile].each {|p| #uploader.store!(p)}
redirect_to contacts_path
flash[:success] = "Uploaded successfully"
end
To make it work you need to specify custom route(config/routes.rb) for your action:
resources :contacts do
collection { post :load_patterns}
end
and to create a form, where you will get params with your uploading files (see p.3)
3) Create form, where you need to specify the option multiple:true in order to allow user to select several files to load (param name with [ ] is a necessary requirement, because we are loading several files) :
<%= form_tag load_patterns_contacts_path, multipart: true, multiple: true do %>
<%= file_field_tag 'qqfile[]', id: "upload_pattern", multiple: true %>
<%= submit_tag "Load", id: "save_pattern", :class => 'btn btn-primary btn-success', multiple: true%>
<% end %>
Then your custom action will work.
Im trying to upload and parse multiple CSV files. What I have so far:
My View
<h3>Upload multiple files</h3>
<%= form_tag({:controller => "multi_uploader", :action => "import"}, :multipart => true) do %>
<em>Upload a tab-separated .txt file to generate new rating sets.</em> <hr/>
<%= file_field_tag :file_1 %>
<hr/>
<%= file_field_tag :file_2 %>
<hr/>
<%= file_field_tag :file_3 %>
<hr/>
<%= file_field_tag :file_4 %>
<hr/>
<%= file_field_tag :file_5 %>
<hr/>
<%= file_field_tag :file_6 %>
<hr/>
<%= submit_tag "Import Data", :class => "btn btn-link"%>
<% end %>
My Controller:
def import
unless params[:file_1].nil?
file_1 = params[:file_1]
RatingSet.multi_uploader(file_1)
end
unless params[:file_2].nil?
file_2 = params[:file_2]
RatingSet.multi_uploader(file_2)
end
unless params[:file_3].nil?
file_3 = params[:file_3]
RatingSet.multi_uploader(file_3)
end
unless params[:file_4].nil?
file_4 = params[:file_4]
RatingSet.multi_uploader(file_4)
end
unless params[:file_5].nil?
file_5 = params[:file_5]
RatingSet.multi_uploader(file_5)
end
unless params[:file_6].nil?
file_6 = params[:file_6]
RatingSet.multi_uploader(file_6)
end
redirect_to "/multi_uploader", :flash => { :notice => "Successfully Uploaded." }
end
My Model method to import file:
def self.multi_uploader(file)
upload = File.open(file.path)
#Parse file and save data to db.
end
In my multi_uploader method, I parse out a key (from the file) for which category the file is supposed to be uploaded to. Everything works as expected when I upload a single file, however if I upload multiple files, the contents of all files are being saved for to a single category, rather than multiple categories. Its as if all files are being treated as a single file, rather than n individual files. What can I change to upload each file individually?
Well, as far as I see. This behavior shouldn't actually be happening. I would suggest another way of doing this code, since it's looking a bit polluted.
def import
(1..x).each do |i| #with x being the max number of files uploaded at the same time
RatingSet.multi_uploader(params["file_#{i}".to_sym])
end
redirect_to "/multi_uploader", :flash => { :notice => "Successfully Uploaded." }
end
Either way, this shouldn't solve your problem. I can't tell why this is happening to be honest.
UPDATE:
Have you considered using: <%= f.file_field :file, :multiple => true %> instead of mutiple file_tags?
Controller:
class SongsController < ApplicationController
.
.
.
def upload
bucket = find_bucket
file = params[:file] edit: previously was file = :file
if bucket
AWS::S3::S3Object.store(file, open(file), bucket)
redirect_to root_path
else
render text: "Couldn't upload"
end
end
private
.
.
.
def find_bucket
AWS::S3::Bucket.find('kanesmusic')
end
end
Upload form in index view:
<h2>Upload a new MP3:</h2>
<%= form_tag upload_path, :method => "post", :multipart => true do %>
<%= file_field_tag :file %>
<%= submit_tag "Upload" %>
<% end %>
Error (edited):
TypeError in SongsController#upload...can't convert AWS::S3::Bucket into String
I'm trying to create this form that can select a file from a users hard drive and upload it.
You need to use params. That where all the vars are stored.
Like so:
params[:file]
But for using file upload (thats slightly different) have a look at the docs
http://guides.rubyonrails.org/form_helpers.html#uploading-files
I am extremely new to rails and I have been looking all over on how to upload a file to a directory in Rails I found this Upload Files but I don't really understand it and I can't get it to work.
This is my View:
<%= form_for :upload, :html => {:multipart => true} do |f| %>
<%= f.file_field :my_file %>
<%= f.submit "Upload" %>
<% end %>
This is my Controller:
def upload
path = File.join("public/folder", upload["datafile"].original_filename)
File.open(path, "wb") { |f| f.write(upload["datafile"].read) }
end
I have also tried the Upload file section of Rails Guides
It says Stack level too deep, can somebody please help and try and explain this to me as simply as possible?
Thanks
uploading in ROR similar
name = upload['datafile'].original_filename
directory = "public/data"
# create the file path
path = File.join(directory, name)
upload_file = File.new(upload['datafile'], "rb").read
# write the file
File.open(path, "wb") {|f| f.write(upload_file) };
use this it may be help you...........