需要更改S3 Bucket(Carrierwave / Fog)中文件的存储“目录”

我正在使用带有3个独立模型的Carrierwave将照片上传到S3。 我保留了上传器的默认设置,即将照片存储在根S3存储桶中。 然后我决定根据模型名称将它们存储在子目录中,例如/ avatars,items /等等,根据它们从上传的模型…

然后,我注意到同名文件被覆盖,当我删除模型记录时,照片没有被删除。

我已经从上传者特定的设置更改了store_dir,如下所示:

def store_dir "items" end 

在模型ID下存储照片的通用版(我使用mongo FYI):

  def store_dir "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end 

这就是问题所在。 我试图将已经进入S3的所有照片移动到S3中的正确“目录”中。 从我准备好的,S3本身没有目录。 我在使用rake任务时遇到了麻烦。 由于我更改了store_dir,因此Carrierwave正在查找之前上传到错误目录中的所有照片。

 namespace :pics do desc "Fix directory location of pictures on s3" task :item_update => :environment do connection = Fog::Storage.new({ :provider => 'AWS', :aws_access_key_id => 'XXXX', :aws_secret_access_key => 'XXX' }) directory = connection.directories.get("myapp-uploads-dev") Recipe.all.each do |l| if l.images.count > 0 l.items.each do |i| if i.picture.path.to_s != "" new_full_path = i.picture.path.to_s filename = new_full_path.split('/')[-1].split('?')[0] thumb_filename = "thumb_#{filename}" original_file_path = "items/#{filename}" puts "attempting to retrieve: #{original_file_path}" original_thumb_file_path = "items/#{thumb_filename}" photo = directory.files.get(original_file_path) rescue nil if photo puts "we found: #{original_file_path}" photo.expires = 2.years.from_now.httpdate photo.key = new_full_path photo.save thumb_photo = directory.files.get(original_thumb_file_path) rescue nil if thumb_photo puts "we found: #{original_thumb_file_path}" thumb_photo.expires = 2.years.from_now.httpdate thumb_photo.key = "/uploads/item/picture/#{i.id}/#{thumb_filename}" thumb_photo.save end end end end end end end end 

所以我循环遍历所有食谱,寻找带有照片的项目,确定旧的Carrierwave路径,尝试使用基于store_dir更改的新路径更新它。 我想如果我只是用新路径更新了photo.key,那就行了,但事实并非如此。

我究竟做错了什么? 有没有更好的方法来完成这里的问题?

这就是我做的工作……

 namespace :pics do desc "Fix directory location of pictures" task :item_update => :environment do connection = Fog::Storage.new({ :provider => 'AWS', :aws_access_key_id => 'XXX', :aws_secret_access_key => 'XXX' }) bucket = "myapp-uploads-dev" puts "Using bucket: #{bucket}" Recipe.all.each do |l| if l.images.count > 0 l.items.each do |i| if i.picture.path.to_s != "" new_full_path = i.picture.path.to_s filename = new_full_path.split('/')[-1].split('?')[0] thumb_filename = "thumb_#{filename}" original_file_path = "items/#{filename}" original_thumb_file_path = "items/#{thumb_filename}" puts "attempting to retrieve: #{original_file_path}" # copy original item begin connection.copy_object(bucket, original_file_path, bucket, new_full_path, 'x-amz-acl' => 'public-read') puts "we just copied: #{original_file_path}" rescue puts "couldn't find: #{original_file_path}" end # copy thumb begin connection.copy_object(bucket, original_thumb_file_path, bucket, "uploads/item/picture/#{i.id}/#{thumb_filename}", 'x-amz-acl' => 'public-read') puts "we just copied: #{original_thumb_file_path}" rescue puts "couldn't find thumb: #{original_thumb_file_path}" end end end end end end end 

也许不是世界上最漂亮的东西,但它确实奏效了。

您需要直接与S3 Objects交互以移动它们。 您可能希望查看Fog gem中的copy_objectdelete_object ,这是CarrierWave用来与S3交互的内容。

https://github.com/fog/fog/blob/8ca8a059b2f5dd2abc232dd2d2104fe6d8c41919/lib/fog/aws/requests/storage/copy_object.rb

https://github.com/fog/fog/blob/8ca8a059b2f5dd2abc232dd2d2104fe6d8c41919/lib/fog/aws/requests/storage/delete_object.rb