ruby on rails - tutorial - Necesita cambiar el "directorio" de almacenamiento de archivos en un Bucket S3(Carrierwave/Fog)
file upload with carrierwave (1)
Estoy usando Carrierwave con 3 modelos separados para subir fotos a S3. Mantuve la configuración predeterminada para el cargador, que era para almacenar fotos en un bucket raíz S3. Luego decidí almacenarlos en subdirectorios según el nombre del modelo, como / avatares, elementos /, etc., según el modelo desde el que se cargaron ...
Luego, noté que los archivos con el mismo nombre se sobrescribían y cuando borré un registro modelo, la foto no se borraba.
Desde entonces, he cambiado el store_dir de una configuración específica para el cargador como esta:
def store_dir
"items"
end
a uno genérico que almacena fotos bajo la ID del modelo (yo uso mongo FYI):
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
Aquí viene el problema. Estoy tratando de mover todas las fotos que ya están en S3 en el "directorio" correcto dentro de S3. Por lo que he preparado, S3 no tiene directorios per se. Estoy teniendo problemas con la tarea de rake. Desde que cambié el store_dir, Carrierwave está buscando todas las fotos cargadas anteriormente en el directorio incorrecto.
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
Así que estoy revisando todas las Recetas, buscando elementos con fotos, determinando la ruta anterior de Carrierwave, tratando de actualizarla con la nueva basada en el cambio de store_dir. Pensé que si simplemente actualizaba photo.key con la nueva ruta, funcionaría, pero no es así.
¿Qué estoy haciendo mal? ¿Hay una mejor manera de realizar la pregunta aquí?
Esto es lo que hice para que esto funcione ...
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
Quizás no sea la cosa más bonita del mundo, pero funcionó.
Necesita interactuar con los Objetos S3 directamente para moverlos. Probablemente quiera mirar copy_object
y delete_object
en la gema Fog, que es lo que CarrierWave usa para interactuar con S3.