2013-09-26 91 views
4

我正在使用Carrierwave和3個獨立模型將照片上傳到S3。我保留了上傳器的默認設置,即將照片存儲在根S3存儲桶中。然後,我決定將它們存儲在子目錄中,根據模型名稱/ avatars,items /等等,根據它們上傳的模型...需要更改S3存儲桶(Carrierwave/Fog)中文件的存儲「目錄」

然後,我注意到同名文件正在被覆蓋,當我刪除模型記錄時,照片未被刪除。

我,因爲從具體的上傳者設置改變了store_dir這樣的:

def store_dir 
    "items" 
    end 

到一個通用的一個,其下的模型ID存儲的照片(我用蒙戈FYI):

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

問題來了。我正試圖將所有已經進入S3的照片轉移到S3中正確的「目錄」中。從我已經準備好的,S3本身沒有目錄。我在耙子任務中遇到問題。由於我更改了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 

也許不是世界上最漂亮的事情,但它的工作。

+0

我會有種期待,以正常工作。是否存在錯誤或文件不存在於您期望的位置?如果數量很少,這可能會正常工作,但特別是對於較大的數字,您可能希望使用copy_object作爲下面的jeremy提及(因爲它可以更快速地完成任何操作,而且無需下載任何內容)。 – geemus

+0

謝謝你,這對我經歷同樣的事情很有幫助。有一件事你可能想知道在將來你可以直接得到文件名,而不必解析路徑: i.picture.file.filename 會在你的情況下做到這一點。 –

回答

5

您需要直接與S3對象進行交互以移動它們。你可能會想看看霧中的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

+0

謝謝Jeremy的幫助,這讓我走上了正確的道路。現在將我的解決方案作爲編輯發佈給任何來此的人。 – aressidi