How to create thumbnails only for image files with Paperclip? - ruby-on-rails

I use the following code to create Assets from the uploaded files:
def upload
uploader = User.find_by_id(params[:uploader_id])
params[:assets].each do |file|
new_asset = uploader.assets.build(:asset => file) # Here the error appears
new_asset.save
end
...
end
I noticed that when I upload non-image files, e.g. my.xlsx, I got the following error:
[paperclip] identify -format %wx%h "C:/temp/stream20110628-460-3vqjnd.xlsx[0]" 2>NUL
[paperclip] An error was received while processing:
#<Paperclip::NotIdentifiedByImageMagickError: C:/temp/stream20110628-460-3vqjnd.xlsx is
not recognized by the 'identify' command.>
(For image files everything works fine: a thumbnail is created, and there is no error.)
Is that because Paperclip tries to create a thumbnail from my.xlsx ?
What configuration will create thumbnails only for image files ?
Here is some relevant code:
class Asset < ActiveRecord::Base
belongs_to :uploader, :class_name => "User"
has_attached_file :asset, :styles => { :thumb => "80x80#" }
end

I used the following nice solution:
before_post_process :image?
def image?
(asset_content_type =~ SUPPORTED_IMAGES_REGEX).present?
end
where:
SUPPORTED_IMAGE_FORMATS = ["image/jpeg", "image/png", "image/gif", "image/bmp"]
SUPPORTED_IMAGES_REGEX = Regexp.new('\A(' + SUPPORTED_IMAGE_FORMATS.join('|') + ')\Z')

Change the has_attached_file line to read:
has_attached_file :asset, :styles => { :thumb=> "80x80#" }, :whiny_thumbnails => false
This will prevent it from raising an error when thumbnails are not created. Note though that it won't raise errors if one occurs when processing an image though.

Related

Paperclip gem with Ruby IO File Object

I'm trying to attach images to an ActiveRecord object with the Paperclip gem. However, I'm trying to attach images, not from a form, but from a script that looks for images in a folder.
Here is my code
file = File.open("some_image.jpg", "r")
my_object.image = file
my_object.save
file.close
The script runs successfully (no errors). However, when I check the website, the images are not showing up. The images were apparently never attached.
I've looked through the documentation, but wasn't able to find anything that solved the problem.
Also, here is MyObject class
class MyObject < ActiveRecord::Base
# Attachments
has_attached_file :image, :styles => { :medium => "300x300>", :thumb => "100x100>" }
validates_attachment_content_type :image, :content_type => ["image/jpg", "image/jpeg", "image/png", "image/gif"]
end
Any ideas?

Can't save image from API with paperclip

I want to save an image from my react app in my rails app.
I post this to my api:
and when I try to save it i get this error:
{
"file":[
"has contents that are not what they are reported to be",
"file type is not acceptable"
],
"file_content_type":[
"file type is not acceptable"
]
}
my model looks like this:
class Photo < ApplicationRecord
validates :title, presence: true
belongs_to :user
has_attached_file :file, styles: { square: "350x233#", medium: "300x300>", thumb: "100x100>" }, default_url: "/images/:style/missing.png"
validates_attachment_content_type :file, content_type: /\Aimage\/.*\z/, message: 'file type is not acceptable'
validates_attachment_size :file, less_than: 10.megabytes, message: 'file size is more than 50MB'
end
and my controller:
def create
uploaded_file = false
if params[:photo][:image]
tempfile = Tempfile.new(params[:photo][:filename])
tempfile.binmode
tempfile.write(Base64.decode64(params[:photo][:image]))
uploaded_file = ActionDispatch::Http::UploadedFile.new(
:tempfile => tempfile,
:filename => params[:photo][:filename],
:original_filename => params[:photo][:filename],
:content_type => Mime::Type.lookup_by_extension(File.extname(params[:photo][:filename])[1..-1]).to_s
)
params[:photo][:file] = uploaded_file
end
params[:photo][:title] = params[:photo][:filename] if params[:photo][:title] == ""
# #picture = Photo.new(photo_params)
#photo = current_user.photos.build photo_params
#photo.save
render json: #photo.errors
end
and in my logs i found this:
Unpermitted parameters: :image, :filename
Command :: file -b --mime '/tmp/homepage.jpg20180415-7-1wa7yr3'
[paperclip] Trying to link /tmp/homepage.jpg20180415-7-1wa7yr3 to /tmp/ba3988db0a3167093b1f74e8ae4a8e8320180415-7-jpgu5m.jpg
[paperclip] Trying to link /tmp/ba3988db0a3167093b1f74e8ae4a8e8320180415-7-jpgu5m.jpg to /tmp/ba3988db0a3167093b1f74e8ae4a8e8320180415-7-147ntu1.jpg
Command :: file -b --mime '/tmp/ba3988db0a3167093b1f74e8ae4a8e8320180415-7-147ntu1.jpg'
[paperclip] Content Type Spoof: Filename homepage.jpg (application/octet-stream from Headers, ["image/jpeg"] from Extension), content type discovered from file command: application/octet-stream. See documentation to allow this combination.
[1m[35m (1.5ms)[0m [1m[35mBEGIN[0m
[paperclip] Trying to link /tmp/ba3988db0a3167093b1f74e8ae4a8e8320180415-7-jpgu5m.jpg to /tmp/ba3988db0a3167093b1f74e8ae4a8e8320180415-7-ndp9hd.jpg
Command :: file -b --mime '/tmp/ba3988db0a3167093b1f74e8ae4a8e8320180415-7-ndp9hd.jpg'
[paperclip] Content Type Spoof: Filename homepage.jpg (application/octet-stream from Headers, ["image/jpeg"] from Extension), content type discovered from file command: application/octet-stream. See documentation to allow this combination.
I didn't get my mistake. Can anyone help me with that upload?
I think the content_type is missing, but I don't know where.
Have you tried using Paperclip's io_adapter to decode the base64 into the attachment object? Something along the lines of:
def create
file = Paperclip.io_adapters.for(params[:photo][:image])
file.original_filename = params[:photo][:filename]
#photo = Photo.new(file: file, user: current_user)
#photo.save
end

Upload image from URL with Paperclip to AWS S3

I have a list of products. For each product, I have one image_url that I want to upload to my AWS S3 account and associate to it.
I am able to do it manually via the form, but with ~1500 products, I can't do it one by one.
My Paperclip config looks like this :
config.paperclip_defaults = {
:url => 'xxxx',
:path => '/:class/:attachment/:id_partition/:style/:filename',
:command_path => "/usr/bin/convert",
:storage => :s3,
:s3_credentials => {
:bucket => "xxx",
:access_key_id => "XXX",
:secret_access_key => "XXXX"
}
}
Here is the code I use to upload manually my image
class Product < ActiveRecord::Base
# This method associates the attribute ":image" with a file attachment
has_attached_file :image, styles: {
thumb: '100x100>',
square: '200x200#',
medium: '300x300>'
}
# Validate the attached image is image/jpg, image/png, etc
validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/
end
Everything goes well, I can see at the end of the log :
[paperclip] saving /products/images/000/001/361/original/xxx.jpg
[AWS S3 200 1.107584 0 retries] put_object(:acl=>:public_read,:bucket_name=>"xxx",:content_length=>47766,:content_type=>"image/jpeg",:data=>Paperclip::UploadedFileAdapter: xxx.jpg,:key=>"products/images/000/001/361/original/xxx.jpg")
[paperclip] saving /products/images/000/001/361/thumb/xxx.jpg
[AWS S3 200 0.444224 0 retries] put_object(:acl=>:public_read,:bucket_name=>"xxx",:content_length=>26502,:content_type=>"image/jpeg",:data=>Paperclip::FileAdapter: 3ef480ec0ebbef3921b4c074897fecc320150625-13674-roduas,:key=>"products/images/000/001/361/thumb/xxx.jpg")
[paperclip] saving /products/images/000/001/361/square/xxx.jpg
[AWS S3 200 0.492781 0 retries] put_object(:acl=>:public_read,:bucket_name=>"xxx",:content_length=>36071,:content_type=>"image/jpeg",:data=>Paperclip::FileAdapter: 3ef480ec0ebbef3921b4c074897fecc320150625-13674-1xrcndz,:key=>"products/images/000/001/361/square/xxx.jpg")
[paperclip] saving /products/images/000/001/361/medium/xxx.jpg
[AWS S3 200 0.553079 0 retries] put_object(:acl=>:public_read,:bucket_name=>"xxx",:content_length=>43927,:content_type=>"image/jpeg",:data=>Paperclip::FileAdapter: 3ef480ec0ebbef3921b4c074897fecc320150625-13674-8dq1h4,:key=>"products/images/000/001/361/medium/xxx.jpg")
But now I want to automate this task (when seeding the database). I added open-uri to retrieve image from their URL.
require 'open-uri'
class Product < ActiveRecord::Base
# This method associates the attribute ":image" with a file attachment
has_attached_file :image, styles: {
thumb: '100x100>',
square: '200x200#',
medium: '300x300>'
}
# Validate the attached image is image/jpg, image/png, etc
validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/
def image_from_url(url)
self.image = URI.escape(url)
end
end
What I basically do is to create a new Product with something like :
Product.create! :name => "Test!!!"
Then try to add image to it :
Product.last.image_from_url "MY_URL"
I have no error with that but it does not work. I can see on the log the conversion for each format (thumb, square, medium) but it is not push to AWS like before.
I found the solution to my question just after finishing to write it.
Maybe it can help someone so I posted it anyway.
The error was that I didn't update the attribute image. So instead of doing :
Product.last.image_from_url "MY_URL"
I did :
Product.last.update_attribute :image, Product.last.image_from_url("MY_URL")
Now the image is generated AND uploaded to AWS

Paperclip says content type is wrong when using an external URL as attachment

I'm using Paperclip 4.2 + Rails 4.1.6 with the following model:
class Post < ActiveRecord::Base
has_attached_file :featured_image, styles: { :medium => "300x300>", :thumb => "100x100>" }
validates_attachment :featured_image, :content_type => { :content_type => ["image/jpeg", "image/gif", "image/png"] }
def featured_image_from_url(url)
self.featured_image = URI.parse(url)
end
end
When I upload a file with the file uploader in my form, everything works fine. The attachment is set and the thumbnails are generated.
However, if I try to use a remote URL pointing to a jpeg image, like specified here, the Post cannot be saved because the attachment has the wrong content type: featured_image_content_type: "binary/octet-stream"
If I force the content type by setting it manually:
post.featured_image_content_type = "image/jpeg"
post.save
then the model is saved successfully.
Hi I don't know whether you found a workaround yet. I have used the following code (amended for your example) to stop Paperclip (4.2.1) raising an exception when a webserver returns an incorrect content-type:
def featured_image_from_url(url)
self.featured_image = URI.parse(url)
# deal with the case where the webserver
# returns an incorrect content-type
adapter = Paperclip.io_adapters.for(featured_image)
self.featured_image_content_type = Paperclip::ContentTypeDetector.new(adapter.path).detect
end
There may be a neater or more correct way!
here is a gem that will help you to download a url to Tempfile so this way you get around the issue with s3 sending stream mime type https://github.com/equivalent/pull_tempfile

Rails Paperclip content_type validation error after convert & display wrong error

I have a problem with the validation of the content type by the Paperclip plug-in:
image.rb (relevant extract)
has_attached_file :photo,
:styles => {:xlarge => "640x512>", :large => "350x280>", :medium => "180x144^",
:thumb => "100x80^", :original => "1280x1280>" },
:convert_options => {:xlarge => "-strip", :large => "-strip",
:medium => "-strip -gravity center -extent 180x144 +repage",
:thumb => "-strip -gravity center -extent 100x80 +repage"},
:default_style => :medium,
:url => "/system/:attachment/:id/:basename_:id_:style.:extension"
validates_attachment_presence :photo
validates_attachment_content_type :photo, :content_type => ['image/jpeg', 'image/png', 'image/gif', 'image/pjpeg', 'image/x-png', 'image/jpeg2000'], :message => 'Uploaded file is not an image'
I'm using nested forms, the image model is the child model of the property model.
During testing the validations of my form I come across some problems. I'm testing validations by uploading a PDF file where the model accepts only images.
output in my form view of: <%= #property.errors.inspect %>
#[#, #message="Uploaded file is not an image">],
"images.photo"=>[#, #message="C:/Users/Michael/AppData/Local/Temp/stream,4272,1.pdf is not recognized by the 'identify' command.">]}>, #base=#>
output in the view of the validation error(s) on the file upload input box:
C:/Users/Michael/AppData/Local/Temp/stream,4272,1.pdf is not recognized by the 'identify' command.
C:/Users/Michael/AppData/Local/Temp/stream,4272,1.pdf is not recognized by the 'identify' command.
C:/Users/Michael/AppData/Local/Temp/stream,4272,1.pdf is not recognized by the 'identify' command.
C:/Users/Michael/AppData/Local/Temp/stream,4272,1.pdf is not recognized by the 'identify' command.
C:/Users/Michael/AppData/Local/Temp/stream,4272,1.pdf is not recognized by the 'identify' command.
2 issues:
issue 1
The input field shows 5 times the same error, that is because I have 5 styles set up in the model. Question is, why does paperclip try to identify (and probably convert the pdf), when you would expect the validation to run first and return already an error before trying to identify and convert? Does Paperclip convert to all the styles before running validations? If yes, is there a way to switch the order of processing, first validation, then styles processing?
issue 2
How can I display the error message of the validation ('Uploaded file is not an image') next to the file upload input box instead of the erros now displayed (5 x the output of the identify command), the latter is of no use to the website user.
Thanks!
I have used
has_attached_file :photo, :whiny => false
and this seems to have helped the error messages. For the error messages, I was using
OBJECT.errors[:photo_content_type]
OBJECT.errors[:photo_file_size]

Resources