问题 Paperclip + S3:将现有文件从一种:路径格式迁移到另一种格式


我有一个模型 avatar 回形针附件。它现在有一条简单的标准路径

has_attached_file :avatar,
  :path => "/:id-:style-:filename"

我需要进入一个混淆的

has_attached_file :avatar,
  :path => "/:id-:hash.:extension"
  :hash_secret => 'asecuresecret'

一切都在使用新图像正常工作,但是如何将存储在S3中的现有文件迁移到新的路径格式,即重命名它们?

我正在使用paperclip 2.7和Rails 3.2

谢谢 !!!


12053
2018-04-20 18:10


起源

对于那些感兴趣的人来说,从哈希转移到非哈希更有趣,我找到的最好的方法是创建一个新的 has_attached_file 进行迁移。 - Joshua Pinter


答案:


这个rake任务应该可以解决问题。我用aws-sdk 1.5.2和ruby 1.9.3p194试了一下。

new_key 应映射到新的回形针路径。别忘了设置 :acl 根据您的需求。

namespace :data do
  desc 'aws images migration'
  task :migrate_images do |t, args|
    s3 = AWS::S3.new(:access_key_id => 'XXX', :secret_access_key => 'XXX')
    bucket = s3.buckets['your-bucket-name']
    bucket.objects.each do |object|
      new_key = object.key.gsub(........)
      new_object = bucket.objects[new_key]
      object.copy_to new_object, {:acl => :public_read}
    end
  end
end

一旦确定新文件正确,就应手动删除原始文件或使用类似任务删除原始文件。


4
2018-06-07 18:56



经过测试 aws-sdk 1.26和ruby 2.0。谢谢,并对接受延迟表示歉意! - dgilperez


如果您只想使用Paperclip而且您不担心重新上传,我会采用另一种方法。

我们假设您有以下内容:

class User
   has_attached_file :image, path: "/:old_path/:filename"
   ...
end

并且您想要迁移到新路径: "/:new_path/:filename"

我的建议是创建一个 FakeUser 使用旧路径并在User模型中更改它。

class FakeUser
   self.table_name = :users
   has_attached_file :image, path: "/:old_path/:filename"
   ...
end

class User
   has_attached_file :image, path: "/:new_path/:filename"
   ...
end

您现在可以编写以下迁移:

FakeUser.find_each do |fake_user|
   User.find(fake_user.id).update(image: fake_user.image)
   fake_user.image.destroy
end

然后,您可以在迁移完成后删除FakeUser模型。

顺便说一下,这种方法也可以完美地从本地文件系统迁移到S3,反之亦然。


11
2018-03-15 09:18



这确实对我有用,我甚至可以通过从真实模型继承假模型来简化它 class FakeUser < User - silva96
迁移所有文件的非常好的解决方案!比我看到的脚本更好。 - Eduardo Almeida


我会写一个rake任务(或者只是一个普通的脚本,如果你愿意,可以在rails上下文中运行)。如果您正在使用aws-s3 gem,请遍历您知道它们具有旧路径格式的模型实例,或尝试在文件名上写一些条件以匹配它们,并逐个移动。

Model.find_in_batches(:batch_size => 500,
      :conditions => "avatar_filename like 'SOMETHING_MATCHING'") do |o|
  AWS::S3::S3Object.rename(old_path(o.avatar), o.avatar.url, 'BUCKET_NAME')
end

如果您已使用新路径定义配置了头像,请编写一个可以根据头像属性构建旧路径的方法。

你可以阅读aws-s3 gem文档 这里 了解如何建立与S3帐户的连接。


0
2018-04-26 16:54