31

我正在使用 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

我似乎无法访问 sanitized_file.rb 中的“extension”或“content_type”之类的项目,所以这有点超出我目前的技能水平。

对此有什么建议或练习,即为上传的文件生成文件名,该文件名与carrierwave默认值一样好(什么都不做,但每个版本都会继续)?似乎它应该很简单,但我偶然发现了这一点。

4

6 回答 6

34

好吧,您的随机文件名生成器的另一个问题是可能会发生冲突,不是吗?您可能会生成一个已经生成的文件名。一种解决方法是根据图像的独特属性(如文件路径)以某种方式生成散列。来自载波组的示例:

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

这将基于当前路径创建一个 MD5 哈希,然后将原始文件的扩展名附加到它。

编辑: carrierwave wiki 添加了一个条目,其中包含一些关于如何为所有版本化文件创建随机和唯一文件名的方法。

于 2011-05-03T04:44:32.210 回答
5

要拥有真正唯一的文件名(几乎不是唯一的),我建议使用 uuid gem。

在 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
于 2012-05-22T15:04:40.507 回答
1

另一个解决方案看起来不错,但是我当时的做法是使用一个挂钩,在创建实例时为新名称创建一个随机字符串,然后:

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

在上传器中。

这很有效,将随机名称生成作为模型的一部分,然后让carrierwave使用它。

我很好奇哪个更快,更有效,合理,健全等。

于 2011-05-04T13:44:28.227 回答
1

来自谷歌组

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
于 2011-07-19T12:19:15.860 回答
1

要使 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
于 2011-08-28T17:15:11.537 回答
0

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.

希望它可以帮助某人。

于 2012-11-27T14:25:51.307 回答