11

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

我来到一个现有的 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 

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

4

1 回答 1

20

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

事情是这样的,一旦你改变了“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

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

于 2014-01-02T09:01:41.347 回答