【问题标题】:How can I migrate CarrierWave files to a new storage mechanism?如何将 CarrierWave 文件迁移到新的存储机制?
【发布时间】:2018-06-22 04:13:20
【问题描述】:

我有一个 Ruby on Rails 站点,其中的模型使用 CarrierWave 进行文件处理,目前使用本地存储。我想开始使用云存储,我需要将现有的本地文件迁移到云端。我想知道是否有人可以指出这样做的方法?

使用模型属性的奖励积分允许我在后台逐行执行此操作而不会中断我的站点以延长停机时间(换句话说,一些模型行仍然具有本地存储,而其他模型行使用云存储)。

我的第一个直觉是为每个使用云存储的模型创建一个新的上传器,所以我在每个模型上都有两个上传器,然后将文件从一个传输到另一个,设置一个属性来指示应该使用哪个文件,直到它们都被转移,然后删除旧的上传器。这似乎有点过分了。

【问题讨论】:

  • 任何答案对你有用吗?

标签: ruby-on-rails activerecord carrierwave


【解决方案1】:

最小到可能为零的停机程序

在我看来,在几乎不停机的情况下完成您想要的最简单和最快的方法是:(我假设您将使用 AWS 云,但类似的过程适用于任何云服务)

  1. 找出并设置您的资产存储桶、存储桶策略等,以使资产可公开访问。
  2. 使用s3cmd(用于与 S3 交互的命令行工具)或 GUI 应用,将整个 assets 文件夹从文件系统复制到 S3 中的相应文件夹。
  3. 在您的应用中,设置carrierwave 并更新您的模型/上传器以用于:fog 存储。
  4. 暂时不要重新启动您的应用程序。而是打开 rails 控制台,并为您的模型检查新资产 URL 是否正确且按计划可访问。例如,对于带有图片资源的视频模型,您可以这样检查:

    Video.first.picture.url
    

    这将为您提供基于更新设置的完整云 URL。复制 URL 并粘贴到浏览器中,以确保您可以正常访问它。

  5. 如果这适用于具有资产的每个模型的至少一个实例,则最好重新启动应用程序。

  6. 重启后,您的所有资产都从云端提供,您的模型中不需要任何迁移或多个上传器。

  7. (基于@Frederick Cheung 的评论):使用s3cmd(或类似的东西)rsyncsync 将资产文件夹从文件系统到 S3,以说明在步骤 2 之间上传的资产和 5 个,如果有的话。

PS:如果您在设置carrierwave 以进行云存储时需要帮助,请告诉我。

【讨论】:

  • 对于在 2 中的复制完成之后但在 5 之前上传的任何资产,您不需要某种追赶过程吗?
  • 好收获。编辑了答案。谢谢。
  • 这似乎是最快的方法。唯一的问题是,如果您想使用不同的命名方案将附件存储在云中,您需要做一些更聪明的事情来进行初始复制。
  • 您好@san,我是使用亚马逊s3服务的新手,请您简要解释一下如何将文件从本地复制到s3。
  • @Sravan 这完全取决于个人喜好和您所在的操作系统。如果你喜欢命令行,你可以使用我上面提到的s3cmd 实用程序。只需谷歌 s3cmd,你就会找到它。有一些 GUI 客户端可以复制文件。一些例子是 ForkLift、Cyber​​duck、Transmit 等。谷歌他们的名字。
【解决方案2】:

我会尝试以下步骤:

  1. 将上传器中的存储更改为 :fog 或您想使用的任何内容
  2. 编写类似rails g migration MigrateFiles 的迁移,让carrierwave 获取当前文件、处理它们并将它们上传到云端。

如果您的模型如下所示:

class Video
  mount_uploader :attachment, VideoUploader
end

迁移将如下所示:

@videos = Video.all
@videos.each do |video|
  video.remote_attachment_url = video.attachment_url
  video.save
end

如果您执行此迁移,应该会发生以下情况:

Carrierwave 会下载每张图片,因为您为附件指定了远程 url(当前位置,例如 http://test.com/images/1.jpg)并将其保存到云端,因为您在上传器中更改了它。

编辑:

由于 San 指出这不会直接起作用,您应该先创建一个额外的列,运行迁移以将所有视频中的当前附件 URL 复制到该列中,然后更改上传器并使用复制的运行上述迁移该新列中的网址。对于另一个迁移,只需再次删除该列。不是那么干净和容易,但在几分钟内就完成了。

【讨论】:

  • 这行不通,因为 video.attachment_url 将为您提供基于云的新路径,而不是旧路径,因为上传者已经更改。
  • 好吧,没有时间尝试这个,但我想你是对的。我调整了答案。
  • 实际上,如果您还暂时将第二个上传器添加到您的模型中,这将起作用 - 我将其作为测试进行了尝试。这样做的一个好处是您可以有条件地将一些附件放在云中并在本地存储一些。这种方法的问题是您需要触摸每个视频模型(这可能取决于您的情况)并且您的附件会被 CarrierWave 重新处理(可能会使该过程变得相当慢)。
【解决方案3】:

当我们使用 Heroku 时,大多数人建议使用 cloudinary。免费且简单的设置。 我的情况是当我们使用云服务并且由于某些原因需要迁移到 aws S3 时。

这是我对上传者所做的:

class AvatarUploader < CarrierWave::Uploader::Base

  def self.set_storage
    if ENV['UPLOADER_SERVICE'] == 'aws'
      :fog
    else
      nil
    end
  end

  if ENV['UPLOADER_SERVICE'] == 'aws'
     include CarrierWave::MiniMagick
  else
     include Cloudinary::CarrierWave
  end

  storage set_storage
end

另外,设置 rake 任务:

task :migrate_cloudinary_to_aws do
    profile_image_old_url = []
    Profile.where("picture IS NOT NULL").each do |profile_image|
      profile_image_old_url << profile_image
    end

   ENV['UPLOADER_SERVICE'] = 'aws'
   load("#{Rails.root}/app/uploaders/avatar_uploader.rb")

   Profile.where("picture IS NOT NULL OR cover IS NOT NULL").each do |profile_image|
     old_profile_image = profile_image_old_url.detect { |image| image.id == profile_image.id }
     profile_image.remote_picture_url = old_profile_image.picture.url
     profile_image.save
   end
end

诀窍是如何通过 env 变量更改上传器提供程序。祝你好运!

【讨论】:

    【解决方案4】:

    我已使用 s3cmd 将 Carrier 波形文件迁移到 Amazon s3,并且可以正常工作。

    以下是要遵循的步骤:

    1. 将上传器的存储类型更改为雾。
    2. 如果您还没有 bucket,请在 Amazon s3 上创建。
    3. 在远程服务器上安装s3cmd sudo apt-get install s3cmd
    4. 配置 s3cmd s3cmd --configure。 您需要在此处输入由 Amazon 提供的公钥和私钥。
    5. 通过此命令同步文件s3cmd sync /path_to_your_files ://bucket_name/
    6. 设置此标志--acl-public 以公开上传文件并避免权限问题。
    7. 重启服务器

    注意事项:

    sync 不会复制您的记录。它将首先检查文件是否存在于远程服务器上。

    【讨论】:

      猜你喜欢
      • 2012-10-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-16
      • 1970-01-01
      • 2013-09-13
      • 2016-11-15
      相关资源
      最近更新 更多