ruby-on-rails - rails - ruby carrierwave tutorial
Cambiar el nombre de los archivos cargados con Carrierwave (6)
Aquí está la solución, cómo cambiar el nombre del archivo, si store_dir
ya contiene el archivo con el nombre exacto :
if File.exists?(Rails.root.join("documents/" + "#{file.filename}")) && !path.to_s.eql?(Rails.root.join("documents/" + original_filename).to_s)
@name ||= File.basename(original_filename, ''.*'') + Digest::MD5.hexdigest(File.dirname(current_path)).from(25)
"#{@name}.#{file.extension}"
else
"#{original_filename}"
end
Nota : Rails.root.join("documents/")
se define como mi store_dir
.
Espero que ayude a alguien.
Estoy usando Carrierwave para subir archivos, y lo tengo funcionando.
Mi problema es intentar cambiar el nombre del archivo cargado.
En el uploader.rb generado hay un método que creo que debería estar usando
def filename
"something.jpg" if original_filename
basename = "what"+orginal_filename if original_filename, works
basename = (0...8).map{65.+(rand(25)).chr}.join if original_filename # will create a random name for each version, e.g. the orginal, the thumb, and the filename in the db, useless
end
Parece que no puedo acceder a elementos como ''extensión'' o ''content_type'' en sanitized_file.rb, así que esto está un poco más allá de mi nivel de habilidad actual en este momento.
¿Alguna sugerencia o ejercicio para hacer esto, es decir, generar nombre de archivo para un archivo cargado que funciona tan bien como el predeterminado de carrierwave (no hacer nada, pero continúa con cada versión)? Parece que debería ser lo suficientemente simple, pero me he tropezado con esto.
Bueno, otro problema con su generador de nombre de archivo aleatorio es que es posible tener colisiones ¿no? Posiblemente pueda generar un nombre de archivo que ya se haya generado. Una forma de hacerlo sería generar de alguna manera un hash basado en propiedades únicas de la imagen, como la ruta del archivo. Un ejemplo, del group carrierwave:
def filename
if original_filename
@name ||= Digest::MD5.hexdigest(File.dirname(current_path))
"#{@name}.#{file.extension}"
end
end
Esto creará un hash MD5 basado en la ruta actual y luego agregará la extensión del archivo original.
Editar: La wiki de carrierwave agregó una entry con algunos métodos sobre cómo crear nombres de archivo aleatorios y únicos para todos los archivos versionados.
Del grupo de Google :
def filename
@name ||= "#{secure_token}.#{file.extension}" if original_filename
end
private
def secure_token
ivar = "@#{mounted_as}_secure_token"
token = model.instance_variable_get(ivar)
token ||= model.instance_variable_set(ivar, ActiveSupport::SecureRandom.hex(4))
end
La otra solución se ve bien, pero la forma en que lo hice fue tener un gancho que creaba una cadena aleatoria para un nuevo nombre en la creación de la instancia, luego:
def filename
"#{model.randomstring}.#{model.image.file.extension}"
end
en el cargador.
Eso funcionó, poniendo la generación de nombres aleatorios como parte del modelo, y luego usando carrierwave.
Tengo curiosidad por saber qué es más rápido, más efectivo, más razonable, más sano, etc.
Para hacer que el prefijo record.id sea el nombre del archivo, puede hacer lo siguiente:
class MyUploader < CarrierWave::Uploader::Base
storage :file
def store_dir
model.class.to_s.underscore.pluralize
end
def filename
model.id ? "#{model.id}-#{original_filename}" : original_filename
end
def url
"/#{store_dir}/#{model.id}-#{model.file_before_type_cast}"
end
end
Para tener un nombre de archivo único (no casi único), recomiendo usar la gema uuid.
en Gemfile agregar:
gem ''uuid''
en file_uploader.rb:
def filename
if original_filename
if model && model.read_attribute(mounted_as).present?
model.read_attribute(mounted_as)
else
@name ||= "#{mounted_as}-#{uuid}.#{file.extension}"
end
end
end
protected
def uuid
UUID.state_file = false
uuid = UUID.new
uuid.generate
end