【问题标题】:How can I reorganize an existing folder hierarchy with CarrierWave?如何使用 CarrierWave 重新组织现有文件夹层次结构?
【发布时间】:2025-12-11 18:15:02
【问题描述】:

我正在尝试使用 CarrierWave 在我的 S3 存储桶中移动文件以重新组织文件夹结构。

我来到一个现有的 Rails 应用程序,其中一个类的所有图像都被上传到一个名为 /uploads 的文件夹中。这会导致问题,如果两个用户上传具有相同文件名的不同图像,第二个图像会覆盖第一个图像。为了解决这个问题,我想根据ActiveRecord 对象实例重新组织文件夹以将每个图像放在自己的目录中。我们正在使用CarrierWave 来管理文件上传。

旧的上传代码有以下方法:

def store_dir
  "uploads"
end

我修改了方法以反映我的新文件存储方案:

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

这对新图像非常有用,但会破坏旧图像的 url。当我更改模型时,现有图像会立即报告其 URL 位于新文件夹中,而图像文件仍存储在 /uploads 中。

> object.logo.store_dir
=> "uploads/object/logo/133"

这是不正确的。此对象应在/uploads 中报告其徽标。

我的解决方案是编写一个脚本来移动图像文件,但我没有在 CarrierWave 中找到正确的方法来移动文件。我的脚本看起来像这样:

MyClass.all.each |image|
  filename = file.name #This method exists in my uploader, returns the file name
  #Move the file from "/uploads" to "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end 

我应该在我的脚本的第三行中做什么来将文件移动到新位置?

【问题讨论】:

  • 您找到解决方案了吗?我有同样的问题。
  • 这可能不适用于您,除非您使用雾,但这是我找到的最佳解决方案,我一直在努力寻找:*.com/questions/19038733/…

标签: ruby-on-rails-3 carrierwave reorganize


【解决方案1】:

警告:这是未经测试的,所以在测试之前请不要在生产环境中使用。

事情是这样的,一旦你改变了“store_dir”的内容,你所有的旧上传都会丢失。你已经知道了。直接与 S3 交互似乎是解决这个问题的最明显方法,因为carrierwave 没有移动功能。

可能有用的一件事是重新“存储”您的上传内容并更改“之前:存储”回调中的“存储目录”路径。

在您的上传器中:

#Use the old uploads directory so carriewave knows where the original upload is
def store_dir
  'uploads'
end

before :store, :swap_out_store_dir

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

然后像这样运行一个脚本:

MyClass.all.each do |image|
  image.image.cache! #create a local cache so that store! has something to store
  image.image.store!
end

之后,验证文件是否已复制到正确的位置。然后,您必须删除旧的上传文件。另外,删除上面的一次性使用上传器代码并将其替换为新的 store_dir 路径:

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

我没有对此进行测试,所以我不能保证它会起作用。请先使用测试数据看看它是否有效,如果您成功了,请在此处发表评论。

【讨论】:

  • 非常适合我。眨眼间就移动了数千个文件。干杯。
  • 我遇到了 replace_script 的问题。但是您可以在没有carrierwave的情况下替换生产中的文件夹和文件。