Переименование загруженных файлов с помощью Carrierwave
Я использую Carrierwave для загрузки файлов, и у меня есть работа.
Моя проблема заключается в попытке изменить имя загруженного файла.
В сгенерированном uploader.rb есть метод, который, я думаю, должен использовать
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
Я не могу получить доступ к элементам типа 'extension' или 'content_type' в файле sanitized_file.rb, поэтому это немного выше моего текущего уровня навыков.
Любые предложения или упражнения для этого, т.е. сгенерировать имя файла для загруженного файла, который работает так же, как и по умолчанию для несущей (ничего не делать, но переносится на каждую версию)? Похоже, это должно быть достаточно простым, но я наткнулся на это.
Ответы
Ответ 1
Ну, еще одна проблема с вашим генератором случайных имен файлов заключается в том, что возможно иметь столкновение не так ли? Вы могли бы сгенерировать имя файла, который уже был сгенерирован.
Один из способов сделать это - это как-то генерировать хеш, основанный на уникальных свойствах изображения, таких как путь к файлу. Например, из несущей волны group:
def filename
if original_filename
@name ||= Digest::MD5.hexdigest(File.dirname(current_path))
"#{@name}.#{file.extension}"
end
end
Это создаст хэш MD5 на основе текущего пути, а затем добавит к нему исходное расширение файла.
Изменить: Вики-страница carrierwave добавила запись с помощью нескольких методов создания случайных и уникальных имен файлов для все версии файлов.
Ответ 2
Чтобы иметь уникальное имя файла (не почти уникальное), я рекомендую использовать жемчужину uuid.
в Gemfile add:
gem 'uuid'
в файле_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
Ответ 3
Другое решение выглядит неплохо, но как я это сделал, тогда должен был быть крючок, который создал случайную строку для нового имени при создании экземпляра, а затем:
def filename
"#{model.randomstring}.#{model.image.file.extension}"
end
в загрузчике.
Это сработало, поставив генерацию случайного имени в качестве части модели, а затем используя носитель.
Мне любопытно, что это быстрее, эффективнее, разумнее, звучать и т.д.
Ответ 4
Из Группа 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
Ответ 5
Чтобы сделать префикс record.id для имени файла, вы можете сделать следующее:
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
Ответ 6
Вот решение, как изменить имя файла, если store_dir
уже содержит файл с точным именем:
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
Примечание: Rails.root.join("documents/")
определяется как my store_dir
.
Надеюсь, что это поможет кому-то.