如何将CarrierWave文件迁移到新的存储机制?
我有一个Ruby on Rails站点,其中模型使用CarrierWave进行文件处理,目前使用的是本地存储。 我想开始使用云存储,我需要将现有的本地文件迁移到云端。 我想知道是否有人可以指出这样做的方法?
使用模型属性的加分点,允许我在后台逐行执行此操作,而不会中断我的站点以延长停机时间(换句话说,某些模型行仍然具有本地存储,而其他模型行则使用云存储)。
我的第一直觉是为每个使用云存储的模型创建一个新的上传器,所以我在每个模型上有两个上传器,然后将文件从一个传输到另一个,设置一个属性来指示应该使用哪个文件,直到它们全部转移,然后删除旧的上传者。 这似乎有点过分。
最小到可能为零的Donwtime程序
在我看来,通过几乎没有停机时间来实现您想要的最简单,最快捷的方法是:(我将假设您将使用AWS云,但类似的程序适用于任何云服务)
- 找出并设置资产桶,存储桶策略等,以使资产可公开访问。
- 使用
s3cmd
(用于与S3交互的命令行工具)或GUI应用程序,将整个资产文件夹从文件系统复制到S3中的相应文件夹。 - 在您的应用中,设置carrierwave并更新模型/上传器
:fog
存储。 -
不要重新启动您的应用程序。 而是启动rails控制台和模型,检查新资产URL是否正确且可按计划访问。 例如,对于带有图片资源的video模型,您可以这样检查:
Video.first.picture.url
这将根据更新的设置为您提供完整的云URL。 复制URL并粘贴到浏览器中以确保您可以正常使用。
-
如果这适用于具有资产的每个模型的至少一个实例,则可以重新启动应用程序。
-
重新启动后,您的所有资产都将通过云提供,并且您的模型中不需要任何迁移或多个上传程序。
-
(基于@Frederick Cheung的评论):使用s3cmd(或类似的东西)
rsync
或将资产文件夹从文件系统sync
到S3,以考虑在步骤2和5之间上传的资产(如果有的话)。
PS:如果您需要帮助为云存储设置carrierwave,请告诉我们。
我尝试以下步骤:
- 将上传器中的存储更改为:雾或您想要使用的内容
- 编写像
rails g migration MigrateFiles
这样的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指出这不会直接起作用,你应该首先创建一个额外的列,运行迁移以将当前attachment_urls从所有video复制到该列,然后更改上传器并使用复制的URL在其中运行上述迁移新栏目。 使用另一个迁移只需再次删除该列。 不是那么简单干净,但在几分钟内完成。
当我们使用Heroku时,大多数人建议使用cloudinary。 免费且简单的设置。 我的情况是当我们使用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变量更改上传器提供程序。 祝好运!
我已经使用s3cmd将Carrier wave文件迁移到Amazon s3并且它可以工作。
以下是要遵循的步骤:
- 将上传器的存储类型更改为雾。
- 如果您还没有,请在Amazon s3上创建一个存储桶 。
- 在远程服务器
sudo apt-get install s3cmd
- 配置s3cmd
s3cmd --configure
。 您需要在此处输入由亚马逊提供的公钥和密钥。 - 通过此命令
s3cmd sync /path_to_your_files ://bucket_name/
文件s3cmd sync /path_to_your_files ://bucket_name/
- 设置此标志
--acl-public
将文件上传为公共文件并避免权限问题。 - 重启你的服务器
笔记:
sync
不会复制您的记录。 它将首先检查文件是否存在于远程服务器上。