Rails Active Storage-如何将本地文件迁移到s3存储桶

时间:2019-06-24 11:45:16

标签: ruby-on-rails amazon-s3 rails-activestorage

之前,我的文件正在存储文件夹中上传。但是现在我想将图像上传到s3存储桶中。如何在s3存储桶上迁移现有的本地数据?

我在这里https://www.stefanwienert.de/blog/2018/11/05/active-storage-migrate-between-providers-from-local-to-amazon/找到了脚本 但是出现

错误
  

NoMethodError(为活动存储调用了私有方法“ open”

那我该如何将本地数据迁移到s3存储桶?

以一种简单的方式存在吗?

2 个答案:

答案 0 :(得分:1)

嗨,我也遇到了这个错误,我将脚本更改为如下所示的rake任务:

# frozen_string_literal: true

namespace :active_storage do
  desc 'Migrate ActiveStorage files from local to Amazon S3'
  task migrate: :environment do
    module ActiveStorage
      class Downloader
        def initialize(blob, tempdir: nil)
          @blob    = blob
          @tempdir = tempdir
        end

        def download_blob_to_tempfile
          open_tempfile do |file|
            download_blob_to file
            verify_integrity_of file
            yield file
          end
        end

        private

        attr_reader :blob, :tempdir

        def open_tempfile
          file = Tempfile.open(["ActiveStorage-#{blob.id}-", blob.filename.extension_with_delimiter], tempdir)

          begin
            yield file
          ensure
            file.close!
          end
        end

        def download_blob_to(file)
          file.binmode
          blob.download { |chunk| file.write(chunk) }
          file.flush
          file.rewind
        end

        def verify_integrity_of(file)
          raise ActiveStorage::IntegrityError unless Digest::MD5.file(file).base64digest == blob.checksum
        end
      end
    end

    module AsDownloadPatch
      def open(tempdir: nil, &block)
        ActiveStorage::Downloader.new(self, tempdir: tempdir).download_blob_to_tempfile(&block)
      end
    end

    Rails.application.config.to_prepare do
      ActiveStorage::Blob.send(:include, AsDownloadPatch)
    end

    def migrate(from, to)
      configs = Rails.configuration.active_storage.service_configurations
      from_service = ActiveStorage::Service.configure from, configs
      to_service   = ActiveStorage::Service.configure to, configs

      ActiveStorage::Blob.service = from_service

      puts "#{ActiveStorage::Blob.count} Blobs to go..."
      ActiveStorage::Blob.find_each do |blob|
        print '.'
        file = Tempfile.new("file#{Time.now}")
        file.binmode
        file << blob.download
        file.rewind
        checksum = blob.checksum
        to_service.upload(blob.key, file, checksum: checksum)
      rescue Errno::ENOENT
        puts 'Rescued by Errno::ENOENT statement.'
        next
      end
    end

    migrate(:local, :s3)
  end
end

答案 1 :(得分:0)

一种更简单的工作方式:

  • amazon 部分添加到您的 config/storage.yml

喜欢

  • 在您的 :amazon

    中将您的存储服务更改为 config/environments/production.rb
  • 将此耙任务添加为 lib/tasks/storage.yml

namespace :storage do
  task reupload: :environment do
    [User, Event].each do |clazz|
      collection = clazz.with_attached_image

      puts "#{clazz} has #{collection.count} images"

      collection.find_each do |user|
        next unless user.image.blob
        user
          .image
          .blob
          .open do |f|
            user.image.attach(io: f, filename: user.image.blob.filename)
          end

        print "."
      end

      puts
    end
  end
end
  • 在本地运行和测试以尝试使用 rake storage:reupload(并在 config.active_storage.service = :amazon 中更改为 config/environments/development.rb

  • 检查本地是否一切正常(您的图像应链接到您的 AWS URL)

  • 上传到您的服务器(例如cap deploy

  • 在你的项目目录中运行RAILS_ENV=production bundle exec rake storage:reupload

  • 稍等片刻,具体取决于您重新上传的图片数量

  • 利润!享受!派对时间!

优点

缺点

  • 没有使它适用于 has_many_attached,但不应有太多变化
  • 你必须选择你的模型
  • 它假定它都被命名为 image(没有什么难以修复的)