Rails cloudinare not uploading image - ruby-on-rails

I've just integrated cloudinary into my rails project and created a view to allow the user to upload an image file.
In my controller I have:
def update
#painting = Painting.find(params[:id])
if params[:image].present?
preloaded = Cloudinary::PreloadedFile.new(params[:image])
raise "Invalid upload signature" if !preloaded.valid?
#painting.image = preloaded.identifier
end
if #painting.update(painting_params)
redirect_to #painting
else
render 'edit'
end
end
In my view:
<%= cl_image_upload_tag(:image) %>
So once the user edits a painting, they can upload the image which will be stored in the #painting model and then it will be saved. After uploading the image, I check cloudinary and find that no image was uploaded. In addition the #painting model has a nil entry for the :image attribute.
Can't see what I'm doing wrong.

Please have a look at the developer tools at the view page, and check whether you have any reported errors there. Specifically, might be related to the jQuery library not being properly included.
You should try to have a look at the sample project. Specifically,
https://github.com/cloudinary/cloudinary_gem/blob/master/samples/photo_album/app/views/photos/new_direct.html.erb#L20

Related

Upload file to S3 from rails server

I would like to upload a file to an Amazon S3 bucket from a rails app. The file comes via a user uploading it. I am having difficulty finding the proper documentation for this because of the different versions of the aws-sdk. Additionally, the acl: :public_read is intentional. I only want authorized users uploading, but anyone should be able to access it.
My current problem is that I am unable to index into a lazy loaded collection. Google provides no useful information for how to not load it lazily.
Here is my relevant code. Note that the controller actions for new and show are empty for now.
messages_controller.rb
def create
# Creates the file object
obj = $S3.bucket(TEST_BUCKET).objects[params[:file].original_filename]
# Uploads the file
obj.write(
file: params[:file],
acl: :public_read
)
end
new.html.erb
<h1>Upload a file</h1>
<%= form_tag messages_path, enctype: 'multipart/form-data' do %>
<%= file_field_tag :file %>
<%= submit_tag 'Upload file' %>
<% end %>
I am using restful routes so the only relevant routing info is resources :messages
I am running rails 6.0.0beta, not that it should matter. I am using version 3 of the aws-sdk gem.
I ended up finding the solution sort of. I do not know how to solve the lazy loading problem but there is a better way.
In the create controller action
def create
obj = $S3.bucket(TEST_BUCKET).object('key_name')
obj.put(body: params[:file].to_io)
end
It'll take some more investigation to apply the attributes to it that I want but this should help anyone else scouring the 3! different versions of the sdk documentation.
The .to_io method on the file is required to get access to the actual file that is in the params[:file] object.

How do can I show image files from outside the public directory?

It's pretty trivial to use the image_tag method to serve an image in the public directory, but what about images that I don't want to be publicly accessible, images for admins only, maybe.
How should my controller and view look so that an image_tag method serves an image from root/private/images rather than root/public. Also, that would be completely secure, right? If I had private images, and wanted to serve them only to admins, a simple if statement to check if the user is an admin and then using an image_tag to serve them the private image from outside the public folder would be secure?
I'd be interested in how to do this without paperclip. (paperclip not even mentioned so it's not a duplicate)
Assuming the image is related to a model such as one with paperclip attached, you could do this. (And I'd really recommend this).
def show
#image = Image.find(params[:id])
published_image = #image.published_image
respond_to do |format|
format.all {
if published_image
send_file published_image.attached_image.path, :type=> published_image.attached_image_content_type
else
raise ActionController::RoutingError.new('Not Found')
end
}
end
end
Assuming you have another way to tell this, you could have all routes beginning with /admin/image route to a controller action, and then there call render file on the rest of the path. Example:
routes.rb
get 'admin/photo/*other', to: 'admin#photos'
admin.controller.rb
def photos
if current_user.admin?
render file: Rails.root.join("private","admin","images",request.path.gsub("/admin/photo/","")
else
render :file => "public/401.html", :status => :unauthorized
end
end
view
image_tag "/admin/photos/id.jpg"
This would in theory work, but it might be more complicated than i'm thinking
Images here would be hosted in public/admin/images, but linked to as /admin/photos/id
I'm not sure how you are handling authentication for admins but assuming you have a separate login.
Store your images as BLOB in MySQL.
Return the requested image files using send_data in rails controller with authentication
This link have an example

"Too many open files" error uploading with Paperclip

I'm using Rails 3.2.13 and Paperclip to upload/store images for a photo website. The form is nested for albums and photos. The Album model contains the lines
attr_accessible :photos_attributes
accepts_nested_attributes_for :photos
And the Photo model
has_attached_file :photo
So the form has an input
<input type="file" name="album[photos_attributes][][photo]" multiple="true">
It works perfectly for a few photos, but when I try to upload a ton, as a user might since it's a photo website, I get the error "Too many open files."
From what I read, it seems like it's because of the way Paperclip handles opening files and not closing them, so I need to manually close them? The Album#create controller action looks like this:
def create
#album = Album.new(params[:album])
if #album.save
redirect_to album_url(#album)
else
render :new
end
end
What do I need to add here to get this to work? Thanks in advance.

Associating a file uploaded with Carrierwave_Direct with an object

I'm uploading files directly to S3 using the carrierwave_direct gem and everything is going smoothly. However, when amazon redirects back to the URL specfied in success_action_redirect, I'm not associating the uploaded file with the object.
My controller looks like
def edit
#excel_version = ExcelVersion.find(params[:id])
#uploader = #excel_version.excel_everest_macro
#uploader.success_action_redirect = edit_admin_excel_version_url
end
def update
#excel_version = ExcelVersion.find(params[:id])
#excel_version.assign_attributes(params[:excel_version])
#excel_version.save
end
And I have a hidden form field in my view that looks like
= form_for #excel_version do |form|
= form.hidden_field :key
So in my update action I just use #excel_version.assign_attributes(params[:excel_version])
and the key returned by Amazon makes it into the model just fine. However, the uploader mounted on the #excel_version object doesn't get url and I can't set up a link to then download the file.
Any suggestions on how I can use the S3 parameters returned to me to associate the file with the model as carrierwave would normally do?
Thanks!
P.S. another answer on here suggested reading the carrier_wave direct documentation on github, which I have and have found unhelpful in this respect.
To associate the image to the model what you can do is create a method in your controller which would use the params from amazon and create the image link
For example you can do -
def image_url
respond_to do |format|
format.json { render :json => { :filelink => "https://s3.amazonaws.com/#{params[:bucket]}/#{params[:key]}" } }
end
end
What this code will do is when amazon does a success redirect to image_url method it will use the parameters "bucket" and "key" to create a exact link to your image. (The params which are sent have both key and the bucket name)
Now you can put this image url in the hidden object on your view so that when the form is posted to the server the url also gets posted along with it. Which you can associate to your model.
Hope this helps. It worked for me.
So my problem was that I had the hidden_field :key field on the wrong form. I mistakenly put the field on the direct_upload_form_for #uploader form that uploads the file to S3.
Of course, you need the :key field on a form that the user returns to after posting the file to S3 (ie at the url passed in to the success_action_redirect method). It is there that S3 will return the key in the params and you can associate it with your model.
Thanks for all the helpful suggestions!

getting text from file uploaded with paperclip

I've got a very simple file upload for a text file using paperclip.
What I want to do is to get the first line of the text file and turn it into a hash I can search against in a database.
I don't think it makes much sense to save the file, then retrieve it, create the hash, and then save it again.
I can't seem to figure out how to get the text of the attached file before saving.
my controller is fairly simple at the moment
def create
#upload = Upload.new(params[:upload])
#upload.user_id=current_user.id
#get the first line of the uploaded file
if #upload.save
redirect_to #upload, :notice =>'Successfully uploaded file."
else
render :action => 'new'
end
end
Going through the documentation, I've seen that paperclip has a to_tempfile, which I assume I can read into a string, but i can't seem to find anywhere that shows me how to do that.
If params[:upload] is the file_field_tag in your form, then it's easier to bypass Paperclip and retrieve the first line of the file directly using Rails, just do this:
first_line = params[:upload].tempfile.readline

Resources