如何迁移Active Storage本地文件至DigitalOcean Spaces并切换服务配置
如何将本地Active Storage文件迁移至DigitalOcean Spaces
前置准备
- 确保
config/environments/production.rb中已正确配置digitalocean_spaces服务:config.active_storage.service = :digitalocean_spaces config.active_storage.services = { digitalocean_spaces: { service: "S3", access_key_id: ENV["DO_SPACES_ACCESS_KEY"], secret_access_key: ENV["DO_SPACES_SECRET_KEY"], region: "nyc3", # 替换为你的Spaces区域 bucket: "your-bucket-name", # 替换为你的Bucket名称 endpoint: "https://nyc3.digitaloceanspaces.com" # 替换为对应区域的endpoint } } - 确认Gemfile中已添加
aws-sdk-s3(DigitalOcean Spaces兼容S3 API,Active Storage依赖该gem),并执行bundle install。
编写迁移任务
在lib/tasks/active_storage_migration.rake中创建Rake任务,用于批量迁移本地Blob到Spaces:
namespace :active_storage do desc "Migrate local Active Storage blobs to DigitalOcean Spaces" task migrate_to_spaces: :environment do # 初始化本地存储服务和Spaces服务实例 local_service = ActiveStorage::Service::DiskService.new(root: Rails.root.join("storage")) spaces_service = ActiveStorage::Service.configure(:digitalocean_spaces, Rails.application.config.active_storage.services) # 遍历所有未迁移的Blob ActiveStorage::Blob.find_each do |blob| next if blob.service_name == "digitalocean_spaces" begin # 从本地读取文件内容 file_content = local_service.download(blob.key) # 上传到DigitalOcean Spaces,保留原文件属性 spaces_service.upload( blob.key, file_content, checksum: blob.checksum, content_type: blob.content_type, disposition: blob.disposition ) # 更新Blob记录的服务标识 blob.update!(service_name: "digitalocean_spaces") puts "✅ 已迁移Blob #{blob.id} (#{blob.filename})" rescue => e puts "❌ 迁移Blob #{blob.id}失败: #{e.message}" end end puts "\n迁移完成!共处理#{ActiveStorage::Blob.count}个Blob,其中#{ActiveStorage::Blob.where(service_name: "digitalocean_spaces").count}个已迁移至Spaces" end end
执行迁移
- 备份数据:务必先备份本地
storage文件夹和数据库,避免迁移过程中数据丢失。 - 运行迁移任务:在终端执行:
rails active_storage:migrate_to_spaces - 验证迁移结果:检查数据库中
active_storage_blobs表的service_name字段,确认所有记录已更新为digitalocean_spaces;同时手动访问几个旧图片链接,确认能正常加载。
后续操作
- 迁移完成后,确保
config.active_storage.service = :digitalocean_spaces已在生产环境配置中生效,重启应用服务。 - 确认所有文件正常访问后,可选择清理本地
storage文件夹(非必需,建议保留备份一段时间)。
注意事项
- 若存在大量文件(数万级以上),建议改用
find_in_batches(batch_size: 100)替代find_each,避免内存溢出。 - 迁移期间建议将应用设为只读模式或暂停服务,防止新文件继续上传到本地存储。
内容的提问来源于stack exchange,提问作者Jamie Crone
相关产品推荐
相关产品推荐

