更新文件时如何在carrierwave中保留相同的文件名(在rails中)

时间:2016-08-15 09:34:41

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

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

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

它只是这样,因为它是我在设置载波时找到的默认方式。最近我意识到,如果更新图像,图像链接将被破坏,因为文件名已更新为使用较新的文件名。因此,如果页面链接到旧图像,则不会使用较新的图像进行更新,而是成为损坏的图像链接。

我希望它在更新映像时保留旧文件名,但无法在文档中找到如何执行此操作以及从Google上搜索

修改

我没有添加很多'用例',因为我没想到这个问题很复杂。

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

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

1 个答案:

答案 0 :(得分:6)

此上下文中的

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

通过这样做:

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

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

但是,自动生成的上传代码中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将永久缓存一次。