ruby-on-rails - 更新文件时如何在carrierwave中保持相同的文件名(在rails中)

标签 ruby-on-rails ruby ruby-on-rails-4 carrierwave

当使用载波更新图像时,我将其设置为使用模型 ID 和原始文件名

def filename
 "#{model.id}-#{original_filename}" if original_filename.present?
end

之所以这样,是因为这是我在设置载波时发现的默认方式。最近我意识到,如果您更新图像,则图像链接会断开,因为文件名已更新为使用较新的文件名。因此,如果一个页面链接到旧图像,它不会更新为新图像,而是变成一个损坏的图像链接。

我希望它在更新图像时保留旧文件名,但无法在文档和谷歌搜索中找到如何执行此操作

编辑

我没有添加很多“用例”,因为我认为问题没有这么复杂。

基本上在网站上有 items 分配有 images。我确实看到了关于 not using only model.id 的评论,@struthersneil 解释了为什么会有该评论。考虑到项目的 images 记录是在创建项目时创建的,在添加图像时它们永远不会是新的(因为它只是更新已经存在的记录)。因此,我认为最好的选择是仅使用 model.id 作为文件名。

我的另一个选择是保留旧图像,这样链接就不会损坏。使用它的主要问题是用户在网站上创建帖子并链接到帖子中的这些图像(帖子会定期更新,所以我不能一次性缓存帖子和帖子中的图像)。图像根据与其关联的项目的新信息更新。一旦发生这种情况,帖子中链接的图片将显示过时的信息,他们每次都必须手动更新到新图片。因此,在这种特殊情况下,让图像链接与正在更新的图像保持一致是最佳选择

最佳答案

original_filename 在此上下文中是上传者刚刚收到的文件的名称。这是文件的原始名称

这样做:

 "#{model.id}-#{original_filename}" if original_filename.present?

您要告诉 CarrierWave 每次都使用文件的新名称。听起来您希望给定模型每次都使用相同的文件名。因此,显而易见的选择就是完全丢弃 original_filename 并单独使用模型 ID。

但是,在自动生成的 uploader 代码中 filename 方法上方的注释是这样说的:

  # Avoid using model.id or version_name here, see uploader/store.rb for details.

这导致我们...

  # Be careful using record ids as filenames. If the filename is stored in the database
  # the record id will be nil when the filename is set. Don't use record ids unless you
  # understand this limitation.

有点麻烦。除非你能保证你的模型总是有一个 id(如果它是新的就不会是真的)那么你不应该使用 model.id 来命名你的文件。

我建议您在初始化时为每个模型生成一个唯一的 file_identifier 字符串(只要 file_identifier 尚未设置),然后只使用这个唯一的字符串作为您的文件名,例如

class Something < ActiveRecord::Base
  mount_uploader :image, SomeImageUploader

  after_initialize do
    unless self.file_identifier
      self.file_identifier = SecureRandom.hex(32)
    end
  end
end

...在您的上传类中...

def filename
  model.file_identifier if original_filename
end

现在您上传的图像将始终覆盖同一个文件。但请注意:您刚刚丢失了图像扩展。这在我的现代版本的 Firefox 中似乎没问题(它可以通过查看图像标题来猜测)但它可能不是最广泛兼容的解决方案。您可以采用 original_filename 的扩展名并将其添加到那里,但是现在如果有人上传了 png 然后又上传了 jpg(结果将是两个不同的文件),您又回到了原来的问题.

您可以在上传时转换为您选择的固定格式,然后文件名 + 扩展名将始终相同。

老实说,如果您接受文件在每次上传后都获得一个新名称,并且只需将旧文件保留一段时间以继续支持拥有旧链接的用户,我认为您会过得更轻松。 (这些链接到底有多久了?如果它位于缓存中,那么为什么只缓存生成的 HTML 而不缓存图像?)如果您计划在应用程序之间使用 CDN 服务,则尤其如此和您的用户。通常的模式是每次都使用新的唯一文件名对文件进行版本控制,CDN 将永久缓存该文件名。

关于ruby-on-rails - 更新文件时如何在carrierwave中保持相同的文件名(在rails中),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38952636/

相关文章:

ruby - RestClient 使用 Resource 进行 GET 操作

ruby - 用于 nil-or-empty 的惯用 Ruby 过滤器?

ruby-on-rails - 使用 Minitest 和 Devise 进行的 Controller 测试失败

ruby-on-rails - 首字母缩略词不会正确复数导致循环依赖

ruby-on-rails - Lion、RVM、Postgresql 和 PG Gem

ruby-on-rails - Rails应用程序流程图生成?

javascript - 在 JavaScript 函数中传递可选参数

ruby - ActiveAdmin ForbiddenAttributesError

ruby-on-rails-4 - 导轨 : Invalid single-table inheritance type error

ruby-on-rails - 在 ubuntu 14.04 x64 上安装 ruby​​-oci8 时出错