Переименование загруженных файлов с Carrierwave - PullRequest
30 голосов
/ 14 декабря 2010

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

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

Ответы [ 6 ]

34 голосов
/ 03 мая 2011

Ну, еще одна проблема с вашим генератором случайных имен файлов в том, что возможно возникновение коллизий, не так ли?Вы могли бы сгенерировать имя файла, которое уже было сгенерировано.Один из способов - это сгенерировать хеш на основе уникальных свойств изображения, таких как путь к файлу.Например, из группы carrierwave group :

def filename 
  if original_filename 
    @name ||= Digest::MD5.hexdigest(File.dirname(current_path))
    "#{@name}.#{file.extension}"
  end
end

Это создаст хеш MD5 на основе текущего пути, а затем добавит к нему расширение исходного файла.

Редактировать: Вики-перевозчик добавил запись с несколькими методами создания случайных и уникальных имен файлов для всех версий файлов.

5 голосов
/ 22 мая 2012

Чтобы иметь реальное уникальное имя файла (не почти уникальное), я рекомендую использовать гем uuid.

в Gemfile добавить:

gem 'uuid'

в 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
1 голос
/ 28 августа 2011

Чтобы просто сделать в качестве префикса 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
1 голос
/ 19 июля 2011

Из Группы 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
1 голос
/ 04 мая 2011

Другое решение выглядит хорошо, но тогда я получил хук, который создал случайную строку для нового имени при создании экземпляра, а затем:

 def filename
    "#{model.randomstring}.#{model.image.file.extension}"
 end

в загрузчике.

Это сработало, поместив генерацию случайных имен в качестве части модели, а затем применив эту несущую.

Мне любопытно, что быстрее, эффективнее, разумнее, звучит и т.д.

0 голосов
/ 27 ноября 2012

Вот решение, как изменить имя файла, если 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/") определяется как мой store_dir.

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

...