I use carrierwave_direct to upload a file , but when the uploaded file is empty I got such error:
<Error><Code>EntityTooSmall</Code><Message>Your proposed upload is smaller than the minimum allowed size</Message><MinSizeAllowed>1</MinSizeAllowed><ProposedSize>0</ProposedSize><RequestId>FE2FE66371A06E29</RequestId><HostId>k3aJ8EtnmPvVxJszZukKYbtEO5Ddrjq/a+FdhqTyL1nZ7afy+msTAA1MiwX8lXvH</HostId></Error>
How to catch this exception??
My code:
collection_action :new_import do
#uploader = #organization.import_file
#organization.save
#uploader.success_action_redirect = import_admin_organization_rooms_url(#organization)
end
collection_action :import do
RoomImportWorker.perform_async(params[:bucket],params[:key],#organization.id,current_user.id)
redirect_to admin_organization_rooms_path(#organization), :notice => "Your request has been accepted! We will inform you via email about the results!"
end
This validation looks good i guess:
https://github.com/jnicklas/carrierwave/wiki/How-to%3A-Validate-attachment-file-size
Related
I have a PDF uploaded in order_items table through paperclip gem. PDF is uploaded successfully and I can see the file uploaded by visiting the S3 url generated.
My problem is, when I am downloading file on active admin it is giving me error:
ActionController::MissingFile
Cannot read file
My member_action in active admin is:
member_action :art_proof, method: :get do
#order = resource
#order_item = #order.order_items.where(id: params[:item_id]).first
#uniform = #order_item.uniform
#stock = #order_item.stock
if #order_item.decoration_preview.url
send_file #order_item.decoration_preview.url,
filename: #order_item.decoration_preview_file_name,
type: #order_item.decoration_preview_content_type
render :nothing => true
else
render layout: false
end
end
I am trying to download file through send_file method. Any idea why this is happening?
I don't think you can use send_file with an S3 URL. Instead I pre-sign the URL and redirect_to the URL. Something like:
aws_resource = Aws::S3::Resource.new(credentials: credentials)
presigner = Aws::S3::Presigner.new(client: aws_resource.client)
redirect_to presigner.presigned_url(:get_object, bucket: bucket_name, key: file.key)
Controller
Save the object
How to Use This Controller to insert image in any folder and image url store in database
def create_json
#user = User.new(userFirstName: params[:userFirstName], userLastName: params[:userLastName], userEmail: params[:userEmail], password: encrypted_password, userImage: params[:userImage])
if #user.save #if save succeeds, redirect to the index action
redirect_to(:action => 'show', id: User.last.id)
else
#if not succeeds, redirect to the index action
redirect_to(:action => 'new')
end end
User(Model) mount_uploader :userImage, AvatarUploader
UsersController -> #user = User.new(user_params)
if #user.save
redirect_to(:action => 'show', id: User.last.id)
else
render :json => data_hash2, :content_type => 'application/json'
end
class AvatarUploader < CarrierWave::Uploader::Base
storage :file
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
def extension_white_list
%w(jpg jpeg gif png)
end end
If You Using Web Service
<form action="http://ruby/controllername/create" lass="new_user" id="new_user" enctype="multipart/form-data" accept-charset="UTF-8" method="post">
View following method for uploading files to app/assets/images/people_profile_images folder
First upload Image like this:
#user =User.new(user_params)
#this will create user form paramaters given
uploaded_file = params[:user][:photo]
#this will add uploaded image or file in uplaoded_fie
if (uploaded_file)
File.open(Rails.root.join('app/assets', 'images/people_profile_images', uploaded_file.original_filename), 'wb') do |file|
file.write(uploaded_file.read)
#user.photo = "/assets/people_profile_images/"+uploaded_file.original_filename
end
else
#user.photo = "/assets/people_profile_images/default_avatar.png"
end
then save user
#user.save
I don't know of an approach that can cover both: image uploading and then saving the url on the database.
You can do one or the other:
1) Use a gem called paperclip that helps upload image files.
See this links:
https://github.com/thoughtbot/paperclip#ruby-and-rails
https://teamtreehouse.com/library/image-uploads-in-ruby-on-rails-41 (paperclip, carrierwave, and dragonfly)
I have used paperclip and it has worked well for me.
OR:
2) Include it as an additional field on your filename.html.erb for your image_url
One caveat, of using this though is that this can be changed and you have no control of the image that might show on your site. Thus, the image_url should be from a reputable CDN or at least from a reputable user uploading to your site.
Create a column url:string in your model. Add it as a hidden field in your form. Set its value to the same as your remote_url using .js
var urladdy = input.remoteurl.val()
input.url.val(urladdy)
This will upload image with carrier wave and also save its url as string.
I have the following model setup:
assignments belong to a user and assignments have many submissions
submissions belong to users and also belong to assignments
submissions have attached files (using paperclip).
I want the assignment user (creator) to be able to download the files (submissions) that belong to the particular assignment.
My routes are structured as follows:
resources :assignments do
resources :submissions
end
So, I think I need to define a download action in my assignments controller, which creates a zip archive of all the submissions belonging to an assignment and then redirects directly to that file url for a download.
def download
#submissions = #assignment.submissions.all
input_filenames = #submissions.file_file_name.all
Zip::File.open(assignment.file.url+"/archive.zip", Zip::File::CREATE) do |zipfile|
input_filenames.each do |filename|
zipfile.add(filename, assignment_submission_file_path(#assignment.id, #submission.id)+ '/' + filename)
end
end
respond_to do |format|
format.html { redirect_to assignment.file.url }
format.json { head :no_content }
end
end
Then in my assignment show page, I have the following:
<%= link_to 'Download', #assignment.file.url(:original, false) %>
But when clicked I get an error returning that the file is missing:
No route matches [GET] "/files/original/missing.png"
So the zip archive file is not being created, and thus my routing to the file doesn't work. It's possible I've done something wrong that is very basic, or that the whole thing needs to be structured differently.
Or my other thought was: do I need to create an empty zip archive in the create action of the assignment controller, so that there is an empty zip archive with a viable path to refer to when I want to add stuff into it? If so, how can I do that with the rubyzip gem?
Thanks!
Here's the answer to my own questions:
create an action in the controller called download and then refer to it properly in the show page:
def download
#assignment = Assignment.find(params[:assignment])
#submissions = #assignment.submissions.all
file = #assignment.file.url(:original, false)
Zip::ZipFile.open(file, create=nil) do |zipfile|
#submissions.each do |filename|
zipfile.add(filename.file_file_name, filename.file.url(:original, false))
end
end
And this is the call to that download action in the show page:
<%= link_to "Download", {:controller => "assignments", :action => "download", :assignment => #assignment.id }%>
I am a beginner of RAILS.
I wrote some code , which validate if the cvs I load is correct
I have also a controller Employee (in this controller I will put validation) :
def import
if params[:csv_file]
Employee.import_from_csv(params[:csv_file], #organization, current_user)
redirect_to admin_organization_employees_path(#organization), :notice => "Your request has been accepted! We will inform you via email about the results!"
else
redirect_to :back, :notice => "Missing file"
end
end
In which place should I put Class CSV_Validator which has lots of code?? In Lib how to use it?
In your model.
Just as rule of thumb, place the bulk of your code in models.
Rails doc
I am new to Rails.
In my project where users have to upload a file, I store it
then I have to parse the file contents and show it in new form.
I have successfully done the file uploading portion,
now how should I read the contents of it?
Try something like this:
upload = params[:your_upload_form_element]
content = upload.is_a?(StringIO) ? upload.read : File.read(upload.local_path)
Very small files can be passed as strings instead of uploaded files, therefore you should check for that and handle it accordingly.
You can open files and read their contents in Ruby using the File class, as this simple example demonstrates:
# Open a file in read-only mode and print each line to the console
file = File.open('afile.txt', 'r') do |f|
f.each do |line|
puts line
end
end
Complete Example
Take, for example, uploading an import file containing contacts. You don't need to store this import file, just process it and discard it.
Routes
routes.rb
resources :contacts do
collection do
get 'import/new', to: :new_import # import_new_contacts_path
post :import, on: :collection # import_contacts_path
end
end
Form
views/contacts/new_import.html.erb
<%= form_for #contacts, url: import_contacts_path, html: { multipart: true } do |f| %>
<%= f.file_field :import_file %>
<% end %>
Controller
controllers/contacts_controller.rb
def new_import
end
def import
begin
Contact.import( params[:contacts][:import_file] )
flash[:success] = "<strong>Contacts Imported!</strong>"
redirect_to contacts_path
rescue => exception
flash[:error] = "There was a problem importing that contacts file.<br>
<strong>#{exception.message}</strong><br>"
redirect_to import_new_contacts_path
end
end
Contact Model
models/contact.rb
def import import_file
File.foreach( import_file.path ).with_index do |line, index|
# Process each line.
# For any errors just raise an error with a message like this:
# raise "There is a duplicate in row #{index + 1}."
# And your controller will redirect the user and show a flash message.
end
end
Hope that helps others!
JP