CarrierWave文件夹结构的最佳实践

Fir*_*gon 3 capistrano ruby-on-rails carrierwave

我一直在搜索这个网站,但似乎无法找到构建图像和文件上传文件夹/文件的最佳方法.我使用以下方法部署Ruby on Rails网站:

  • CarrierWave(上传)
  • Capistrano(部署)
  • 亚马逊S3(存储)
  • Capistrano(部署)

该网站允许用户设置他们将上传图像的配置文件.我想使用一个文件夹结构,可以很好地扩展到数千(或数万)用户上传多个图像.

目前我正在使用默认的CarrierWave目录结构:

def store_dir
  "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
Run Code Online (Sandbox Code Playgroud)

但我认为或许在文件夹名称中包含user_id会更好?将此文件夹移到文件夹之外是否更好public/uploads?我不应该在开发,生产和测试环境中使用不同的文件夹吗?我想以最佳方式覆盖store_dir,对于拥有数千名用户的网站,每个配置文件上传大约15个文件(存储为完整大小,个人资料和缩略图大小).

Jas*_*uck 8

普通的文件夹结构应该支持帽子,主要是避免冲突,并确保您用于整个站点的图像的关联是一致的.由于这些原因,您不希望将所有图像显然存储在一个文件夹中.

但我认为或许在文件夹名称中包含user_id会更好?

我不推荐这个,它可能会导致比它的价值更多的问题.使用模型类和你正在做的id应该是足够的,并且上传者可能在映射图像时遇到问题,例如当不是上传者的用户试图查看图像时.

将此文件夹移到public/uploads文件夹之外是否更好?

由于您使用的是Amazon S3,因此您的图像实际上并不存储在项目的公共/上传中(如果您所指的位置).这应该只是Carrierwave在上传/调整文件大小时使用的临时文件.如果您担心空间/安全性,您可能需要查看此内容并在必要时根据您的需要进行调整.

我不应该在开发,生产和测试环境中使用不同的文件夹吗?

如果您愿意,可以使用不同的文件夹:

def store_dir
  "#{Rails.env}/uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
Run Code Online (Sandbox Code Playgroud)

或者在Amazon S3上使用不同的存储桶(推荐):

config/initializers/fog.rb这样的事情:

CarrierWave.configure do |config|
  config.storage = :fog
  config.fog_credentials = {
    :provider              => <provider>,
    :aws_access_key_id     => <id>,
    :aws_secret_access_key => <key>
  }
  if Rails.env == "production"
    config.fog_directory = 'production'
  elsif Rails.env == "development"
    config.fog_directory = 'development'
  elsif ...
    config.fog_directory = '...'
  end
end
Run Code Online (Sandbox Code Playgroud)

或者你可以在单独的环境文件中做类似的事情.

我想以最佳方式覆盖store_dir,对于拥有数千名用户的网站,每个配置文件上传大约15个文件(存储为完整大小,个人资料和缩略图大小).

这个存储目录结构应该工作正常,只要调整大小你应该查看指南.

更新:

对于文件名,我肯定会建议将其更改为随机字符串,以便您可以避免文件夹本身中任何潜在的命名冲突.有人可以上传me.jpg2个不同的文件.这就是说我是这样做的.

your_uploader.rb

添加一个文件名方法,将随机化当前文件名.

 def filename
   random_token = Digest::SHA2.hexdigest("#{Time.now.utc}--#{model.id.to_s}").first(20)
   ivar = "@#{mounted_as}_secure_token"
   token = model.instance_variable_get(ivar)
   token ||= model.instance_variable_set(ivar, random_token)
   "#{token}.jpg" if original_filename
  end
Run Code Online (Sandbox Code Playgroud)

这种特殊的安排可能有点矫枉过正,但对我来说证明是足够的.

希望这可以帮助!

  • 我会更新答案.我肯定会建议改变它. (2认同)
  • 最好更改它,因为原始文件名可能会导致XSS攻击 (2认同)