我正在使用带有 3 个不同型号的 Carrierwave 将照片上传到 S3。我保留了上传器的默认设置,即将照片存储在根 S3 存储桶中。然后我决定根据模型名称将它们存储在子目录中,例如/avatars、items/等,基于它们上传的模型...
然后,我注意到同名文件被覆盖,当我删除模型记录时,照片并没有被删除。
从那以后,我将 store_dir 从特定于上传者的设置中更改为如下所示:
def store_dir
"items"
end
到将照片存储在模型 ID 下的通用模型(我使用 mongo 仅供引用):
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 对象交互才能移动它们。您可能想查看 Fog gem 中的 copy_object
和 delete_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
关于ruby-on-rails - 需要更改 S3 Bucket (Carrierwave/Fog) 中文件的存储 "directory",我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19038733/