Rails 4 and paperclip - Stop the :original style file upload to copy it from an S3 remote directory

后端 未结 1 640
终归单人心
终归单人心 2021-01-26 02:53

I use Paperclip 4.0.2 and in my app to upload pictures.

So my Document model has an attached_file called attachment

The attachment has few styles, s

相关标签:
1条回答
  • 2021-01-26 03:36

    New Answer:

    paperclip attachments get uploaded in the flush_writes method which, for your purposes, is part of the Paperclip::Storage::S3 module. The line which is responsible for the uploading is:

    s3_object(style).write(file, write_options)
    

    So, by means of monkey_patch, you can change this to something like:

    s3_object(style).write(file, write_options) unless style.to_s == "original" and @queued_for_write[:your_processed_style].present?
    

    EDIT: this would be accomplished by creating the following file: config/initializers/decorators/paperclip.rb

    Paperclip::Storage::S3.class_eval do
      def flush_writes #:nodoc:
        @queued_for_write.each do |style, file|
        retries = 0
          begin
            log("saving #{path(style)}")
            acl = @s3_permissions[style] || @s3_permissions[:default]
            acl = acl.call(self, style) if acl.respond_to?(:call)
            write_options = {
              :content_type => file.content_type,
              :acl => acl
            }
    
            # add storage class for this style if defined
            storage_class = s3_storage_class(style)
            write_options.merge!(:storage_class => storage_class) if storage_class
    
            if @s3_server_side_encryption
              write_options[:server_side_encryption] = @s3_server_side_encryption
            end
    
            style_specific_options = styles[style]
    
            if style_specific_options
              merge_s3_headers( style_specific_options[:s3_headers], @s3_headers, @s3_metadata) if style_specific_options[:s3_headers]
              @s3_metadata.merge!(style_specific_options[:s3_metadata]) if style_specific_options[:s3_metadata]
            end
    
            write_options[:metadata] = @s3_metadata unless @s3_metadata.empty?
            write_options.merge!(@s3_headers)
    
            s3_object(style).write(file, write_options) unless style.to_s == "original" and @queued_for_write[:your_processed_style].present?
          rescue AWS::S3::Errors::NoSuchBucket
            create_bucket
            retry
          rescue AWS::S3::Errors::SlowDown
            retries += 1
            if retries <= 5
              sleep((2 ** retries) * 0.5)
              retry
            else
              raise
            end
          ensure
            file.rewind
          end
        end
        after_flush_writes # allows attachment to clean up temp files
        @queued_for_write = {}
      end
    end
    

    now the original does not get uploaded. You could then add some lines, like those of my origninal answer below, to your model if you wish to transfer the original to its appropriate final location if it was uploaded to s3 directly.

    Original Answer:

    perhaps something like this placed in your model executed with the after_create callback:

        paperclip_file_path = "relative/final/destination/file.jpg"
        s3.buckets[BUCKET_NAME].objects[paperclip_file_path].copy_from(relative/temp/location/file.jpg)
    

    thanks to https://github.com/uberllama

    0 讨论(0)
提交回复
热议问题