【问题标题】:CarrierWave folder structure best practicesCarrierWave 文件夹结构最佳实践
【发布时间】:2012-12-15 20:45:45
【问题描述】:

我一直在搜索此站点,但似乎找不到为图像和文件上传构建文件夹/文件的最佳方式。我正在使用以下方式部署 Ruby on Rails 网站:

  • CarrierWave(上传)
  • Capistrano(部署)
  • Amazon S3(存储)
  • Capistrano(部署)

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

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

def store_dir
  "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end

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

【问题讨论】:

  • 请理解我已经对此进行了很多搜索,并希望我尊重这个网站上的规则——我很少需要问纯粹的编码问题,因为这个网站上已经有了很棒的答案。任何关于文件夹/文件结构的好建议或部署提示都将被接受为答案。

标签: ruby-on-rails capistrano carrierwave


【解决方案1】:

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

但我认为最好在文件夹名称中包含 user_id?

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

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

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

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

您可以根据需要使用不同的文件夹:

def store_dir
  "#{Rails.env}/uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end

或者在 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

或者您可以在单独的环境文件中执行类似的操作。

我想以最好的方式覆盖 store_dir,以便有数千名用户上传每个配置文件大约 15 个文件(存储为完整大小、配置文件和缩略图大小)的网站。

这个存储目录结构应该可以正常工作,至于调整大小,您应该查看the guide

更新:

对于文件名,我绝对建议将其更改为随机字符串,这样您就可以避免文件夹本身内任何潜在的命名冲突。有人可以为 2 个不同的文件上传 me.jpg 并非不可能。话虽如此,我就是这样做的。

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

这种特殊的安排可能有点矫枉过正,但对我来说已经足够了。

希望这会有所帮助!

【讨论】:

  • 这对 Jason 非常有帮助,我将在接下来的几天内实施,并告诉你进展如何。
  • 我有一个问题是是否最好保留上传文件的原始文件名?意思是,如果有人上传“some-long-filename.jpg”,可以保留这个名称,或者将文件重命名为“12345.jpg”等数字是正常的。我刚刚注意到一些网站上的这种重命名。
  • 我会更新这个答案。我肯定会建议更改它。
  • 最好更改它,因为原始文件名会导致 XSS 攻击
  • 文件夹里面有很多文件夹不是问题吗? (每个模型 1 个文件夹)
猜你喜欢
  • 2017-04-21
  • 2016-06-18
  • 1970-01-01
  • 2019-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-03
  • 1970-01-01
相关资源
最近更新 更多