Подтвердить что ты не робот

Переименование загруженных файлов с помощью 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, поэтому это немного выше моего текущего уровня навыков.

Любые предложения или упражнения для этого, т.е. сгенерировать имя файла для загруженного файла, который работает так же, как и по умолчанию для несущей (ничего не делать, но переносится на каждую версию)? Похоже, это должно быть достаточно простым, но я наткнулся на это.

4b9b3361

Ответ 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.

Надеюсь, что это поможет кому-то.