问题
I have a model that uses Paperclip to handle images. When the image gets uploaded a preview is made for some javascript cropping and then a thumbnail and preview sizes are made from the chosen cropping. Giving us 3 images on S3 total:
- Original Image
- Preview (from the user selected cropping)
- Thumb (from the user selected cropping)
The code in the model for the attachment is:
has_attached_file :picture, ASSET_INFO.merge(
:whiny => false,
:styles => { :thumb => '200>x200#', :preview => '400x300>' },
:processors => [:jcropper],
:preserve_files => true
)
We have some functionality that allows a user to make a copy of an object for their own purposes and we want to copy the images over. I thought that just doing a simple
new_my_model.picture = original_my_model.picture if original_my_model.picture_file_name #no file name means no picture
would get the job done, and it does, but only kind of.
It's copying the picture and then reprocessing the preview and thumbnails based on what's set up in the model.
What I would like to do instead is copy all 3 existing images (original, thumb, and preview) to the new object as they are for the original one and then save them in the appropriate location on S3, skipping the resizing/cropping.
Can anyone point me in the right direction? I've searched online and can't seem to find anything and everything I try doesn't seem to work. Doing a .dup
on the original picture causes an exception, so that idea is out.
回答1:
Manual cropping breaks Paperclip's automatic cropping/resizing scheme. That's okay until you want to duplicate an attachment from one model to another. You have two options: Save the cropping parameters for each style in database, and call "reprocess!" after duplicating (based on the this question).
I have no intention to save cropping data in database, it's totally useless. I decided to blindly duplicate the images myself, directly calling S3. Not optimal, but works:
module Customizable
def duplicate copy_args
new_model = self.dup
copy_args.each {|key, val| new_model[key] = val}
new_model.save
s3 = AWS::S3.new(self.image.s3_credentials)
bucket = s3.buckets[self.image.s3_credentials[:bucket]]
styles = self.image.styles.keys.insert(0, :original)
begin
styles.each do |style|
current_url = self.image.path(style)
current_object = bucket.objects[current_url]
if current_object.exists?
# actually asking S3 if object exists
new_url = new_model.image.path(style)
new_object = bucket.objects.create(new_url)
# this is where the copying takes place:
new_object.copy_from(current_object)
new_object.acl = current_object.acl
end
end
rescue Exception => err
return err
end
return true
end
end
In my model:
class Product < ActiveRecord::Base
# ...
has_attached_file :image, ...
# ...
include Customizable
def customize product_id
return self.duplicate({:in_sale => false}) #resetting some values to the duplicated model
end
# ...
end
来源:https://stackoverflow.com/questions/17603045/copy-all-styles-of-a-paperclip-attachment-to-new-object-s3