Ruby on rails “需要更改存储空间”;目录";S3存储桶中的文件数量(Carrierwave/Fog)

Ruby on rails “需要更改存储空间”;目录";S3存储桶中的文件数量(Carrierwave/Fog),ruby-on-rails,ruby-on-rails-3,amazon-s3,carrierwave,fog,Ruby On Rails,Ruby On Rails 3,Amazon S3,Carrierwave,Fog,我使用Carrierwave和3个独立的模型将照片上传到S3。我保留了上传程序的默认设置,即将照片存储在根S3存储桶中。然后我决定根据模型名称将它们存储在子目录中,如/avatars、items/等。基于它们从中上载的模型 然后,我注意到同名文件被覆盖,当我删除模型记录时,照片没有被删除 此后,我将store_dir从特定于上传程序的设置更改为: def store_dir "items" end 将照片存储在模型ID下的通用模型(我使用mongo供参考): 问题来了。我正在尝

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

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

此后,我将store_dir从特定于上传程序的设置更改为:

  def store_dir
    "items"
  end
将照片存储在模型ID下的通用模型(我使用mongo供参考):

问题来了。我正在尝试将所有已经进入S3的照片移动到S3中正确的“目录”中。据我所知,S3本身没有目录。我在执行rake任务时遇到了麻烦。由于我更改了store_目录,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对象交互才能移动它们。您可能需要查看Fog gem中的
copy_object
delete_object
,这是CarrierWave用来与S3交互的


我希望这也能奏效。是否存在错误或文件不存在于您期望的位置?如果有一个小的数字,这可能会很好,但特别是对于一个更大的数字,你可能想使用下面jeremy提到的copy_对象(因为它做任何事情都要快得多,你不需要下载任何东西)。感谢这一点,这对我经历同样的事情很有帮助。将来您可能想知道的一件事是,您可以直接获取文件名,而无需解析路径:i.picture.file.filename在您的情况下就可以了。感谢Jeremy的帮助,这让我走上了正确的道路。现在将我的解决方案发布为其他任何人的编辑。
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