Rails 3-2. Multiple file uploading. Ruby issue - ruby-on-rails

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.

Related

How to set mail attachments without saving file in database?

I have created simple application form and i was trying to upload file and send it as email attachment. And i did it with this approach:
class ApplyController < ApplicationController
def prepare_email_content
ApplyMailer.with(params).apply.deliver_now
end
end
class ApplyMailer < ApplicationMailer
def apply
#company = Company.find(params[:company_id])
#candidate = params[:name]
#candidate_mail = params[:email]
#email = #company.email
attachments[params[:cv].original_filename] = params[:cv].read
mail to: #email, subject: 'Hello'
end
end
<h1>APPLY</h1>
<%= form_tag(apply_path, method: :post, multipart: true) do %>
<%= label_tag(:name, "First and last name:") %>
<%= text_field_tag(:name) %>
<%= label_tag(:email, "Email:") %>
<%= text_field_tag(:email) %>
<%= hidden_field_tag :company_id, params[:company_id] %>
<%= file_field_tag 'cv' %>
<%= submit_tag "Search", :name => nil %>
<% end %>
<%= link_to 'All offers', hello_path %>
Everything was working fine - i have tested application and it was fine. Then i have developed my application and when i come back to testing i started getting this error:
On the way i have installed some gems and updated few of them. I was checking out to commit where this feature was working and it is. But i'm not able to find any differences in my code. There were some changes in /.idea folder but i don't know if any of this files could trigger this issue.
I'm using rails 6.0.3 and ruby 2.5.8
EDIT
I can see that there is a problem inside called methods. Looks like it cannot find #sort_order value and it sets data value as nil. But i have no idea how to change working of this.
Replace the line you're attaching the file with
attachments["#{params[:cv].original_filename}"] = File.read(params[:cv].path)
Even though you're not saving the file, there is a still a local path to grab the file from.
Also, you should really consider passing the parameters to the mailer from the controller, rather than passing params in its entirety. That way if the information or format of the upload is incorrect, you can redirect back to the form and bypass sending the email.

Can't find submitted file in params

All I'm trying to do is parse a file with Rails, but I can't for the life of me pass it through to my controller. I can't even get the file name or path to show up in the submitted params.
My form:
<%= form_tag({url: upload_path}, method: :patch, multipart: true) do %>
<%= file_field(:user, :csv, :multiple => false, class:"file-field") %>
<%= submit_tag 'Submit', class:"btn" %>
<% end %>
My controller:
def upload
file = params[:user][:csv] #params[:user] is nil
#parse file
end
According to the rails docs, I thought the file should be contained in params[:user][:csv], but I must be misinterpreting something because params[:user][:csv] is nil, and neither "user" or "csv" show up anywhere in the params.
I want to be able to get the file path, and then using that, parse the file. What am I doing wrong?
Use this for file_field_tag
<%= file_field_tag('user["csv"]', :multiple => false, class:"file-field") %>
Options should go after name and I don't understand what is :csv in that case if :user is name

Rails CSV file upload problems

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

How to append user_id to Rails file upload?

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('.'))

Carrierwave / Fog to S3 fails with files over 5mb

I have a Rails 4 app that uses Carrierwave and Fog to upload files to Amazon S3. The servers the app uses is Nginx and Thin.
The problem I'm having is when uploading files over 5mb.
I've tried searching everywhere for a way to get it working, I've tried CarrierwaveDirect and still can't get it to work.
Here is my Carrierwave config:
config.fog_directory = 'aws-bucket-name'
config.fog_public = false
config.fog_attributes = { multipart_chunk_size: 5242880 }
config.max_file_size = 200.megabytes # CarrierwaveDirect option
Here are the controller actions:
def new
#file = DownloadFile.new
end
def create
#file = DownloadFile.new
#file.file = params[:download_file][:file]
if #file.save
redirect_to downloads_path
else
render :new
end
end
And the form:
<%= form_for #file, multipart: true do |f| %> <!-- even tried with `multipart` wrapped in `html: {}` -->
<%= f.label :file %>
<%= f.file_field :file %>
<%= f.button t(:upload) %>
<% end %>
I can upload small files just fine, but when it comes to files that are over 5mb, the form just redisplays. No errors, no errors in the logs, nothing.
With Carrierwave Direct it looks like you would need to setup the form slightly differently (as it would need to set the url to one on S3, rather than on your own server). If you are dealing with large files this may be preferable as large files would otherwise tie up a process for an extended time. To make that work it looks like you'll want to use the direct_upload_form_for helper method instead of plain form_for, something like:
<%= direct_upload_form_for #uploader do |f| %>
<%= f.file_field :avatar %>
<%= f.submit %>
<% end %>
For a bit more detail on that, see: https://github.com/dwilkie/carrierwave_direct#rails

Resources