Ruby-on-rails 使用 Carrierwave 重命名上传的文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4443494/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 23:53:41  来源:igfitidea点击:

Renaming uploaded files with Carrierwave

ruby-on-railsrubyfile-uploadcarrierwave

提问by waving

I'm using Carrierwave to upload files, and I have it working.

我正在使用 Carrierwave 上传文件,并且可以正常工作。

My issue is attempting to change the name of the uploaded file.

我的问题是尝试更改上传文件的名称。

In the generated uploader.rb there is a method I think I should be using

在生成的 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

I can't seem to access items like 'extension' or 'content_type' in sanitized_file.rb, so this is a bit beyond my current skill level right now.

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

Any suggestions or exercises for doing this, i.e. generate filename for an uploaded file that works as well as the carrierwave default (do nothing, but does carry on to each version)? Seems like it should be simple enough but I've stumbled over this.

这样做的任何建议或练习,即为上传的文件生成文件名,该文件与载波默认值一样工作(什么都不做,但会继续到每个版本)?似乎它应该足够简单,但我偶然发现了这一点。

回答by Hyman Chu

Well, another problem with your random filename generator is that it's possible to have collisions isn't it? You could possibly generate a filename that was already generated. One way to go about it would be to somehow generate a hash based on unique properties of the image, like file path. An example, from the carrierwave group:

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

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

This will create an MD5 hash based on the current path and then append the original file's extension to it.

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

Edit:The carrierwave wiki added an entrywith a few methods on how to create random and unique filenames for all versioned files.

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

回答by ramigg

To have a real unique filename (not almost unique) I recommend to use the uuid gem.

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

in Gemfile add:

在 Gemfile 中添加:

gem 'uuid'

in file_uploader.rb:

在 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

回答by blueblank

The other solution looks good, but how I did it then was to have a hook that created a random string for a new name on instance creation, then:

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

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

in the uploader.

在上传器中。

That worked, putting the random name generation as part of the model, then having carrierwave use that.

那行得通,将随机名称生成作为模型的一部分,然后让载波使用它。

I am curious which is faster, more effective, reasonable, sound, etc.

我很好奇哪个更快、更有效、更合理、更合理等。

回答by bouchard

From the Google Group:

来自谷歌集团

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

回答by T.N.T.

To just make the record.id prefix the filename you can do the following:

要仅将 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

回答by mArtinko5MB

Here is the solution, how to change the name of the file, if store_diralready contains the file with the exact name:

这是解决方案,如果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

Note: Rails.root.join("documents/")is defined as my store_dir.

注意Rails.root.join("documents/")定义为我的store_dir.

Hope it helps someone.

希望它可以帮助某人。