将Paperclip S3图片迁移到新的URL/路径格式

5
有没有推荐的技术来迁移大量的Paperclip S3图片到新的:url和:path格式?
原因是升级到Rails 3.1后,在裁剪后不再显示新版本的缩略图(之前缓存的版本会显示)。这是因为文件名不再更改(因为Rails 3.1中删除了asset_timestamp)。我正在使用:url/path格式中的:fingerprint,但这是从原始文件生成的,而在裁剪时不会更改。
我打算在url/path格式中插入:updated_at,并在裁剪期间更新attachment.updated_at,但在实施该更改后,所有现有图像都需要移动到它们的新位置。这大约是重命名超过50万张图片在S3上。
此时,我正在考虑先将它们复制到新位置,然后部署代码更改,然后移动任何被遗漏的图像(即在复制后上传的图像),但我希望有更简单的方法...有什么建议吗?
2个回答

6

为了支持图像裁剪,我不得不更改我的纸夹路径,最终创建了一个rake任务来帮助解决问题。

namespace :paperclip_migration do

  desc 'Migrate data'
  task :migrate_s3 => :environment do
    # Make sure that all of the models have been loaded so any attachments are registered
    puts 'Loading models...'
    Dir[Rails.root.join('app', 'models', '**/*')].each { |file| File.basename(file, '.rb').camelize.constantize }

    # Iterate through all of the registered attachments
    puts 'Migrating attachments...'
    attachment_registry.each_definition do |klass, name, options|
      puts "Migrating #{klass}: #{name}"
      klass.find_each(batch_size: 100) do |instance|
        attachment = instance.send(name)

        unless attachment.blank?
          attachment.styles.each do |style_name, style|
            old_path = interpolator.interpolate(old_path_option, attachment, style_name)
            new_path = interpolator.interpolate(new_path_option, attachment, style_name)
            # puts "#{style_name}:\n\told: #{old_path}\n\tnew: #{new_path}"
            s3_copy(s3_bucket, old_path, new_path)
          end
        end
      end
    end

    puts 'Completed migration.'
  end

  #############################################################################
  private

  # Paperclip Configuration
  def attachment_registry
    Paperclip::AttachmentRegistry
  end

  def s3_bucket
    ENV['S3_BUCKET']
  end

  def old_path_option
    ':class/:id_partition/:attachment/:hash.:extension'
  end

  def new_path_option
    ':class/:attachment/:id_partition/:style/:filename'
  end

  def interpolator
    Paperclip::Interpolations
  end

  # S3
  def s3
    AWS::S3.new(access_key_id: ENV['S3_KEY'], secret_access_key: ENV['S3_SECRET'])
  end

  def s3_copy(bucket, source, destination)
    source_object = s3.buckets[bucket].objects[source]
    destination_object = source_object.copy_to(destination, {metadata: source_object.metadata.to_h})
    destination_object.acl = source_object.acl
    puts "Copied #{source}"
  rescue Exception => e
    puts "*Unable to copy #{source} - #{e.message}"
  end

end

嘿@jessecurry,这被证明能够工作吗?无论我的路径是什么?它也保存数据库? - Hamdan
@Hamdan,这在当时对我起作用了,你需要确保旧路径和新路径选项对于你的配置是正确的。 - jessecurry

2

没有找到可行的方法来迁移到新的URL格式。我最终重写了Paperclip::Attachment#generate_fingerprint,使其附加:updated_at


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接