我正在使用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
也許不是世界上最漂亮的事情,但它的工作。
我會有種期待,以正常工作。是否存在錯誤或文件不存在於您期望的位置?如果數量很少,這可能會正常工作,但特別是對於較大的數字,您可能希望使用copy_object作爲下面的jeremy提及(因爲它可以更快速地完成任何操作,而且無需下載任何內容)。 – geemus
謝謝你,這對我經歷同樣的事情很有幫助。有一件事你可能想知道在將來你可以直接得到文件名,而不必解析路徑: i.picture.file.filename 會在你的情況下做到這一點。 –