s3のバケットの名前を変更することは出来ないので、URLをファイルアップロード後に変更する必要が出てきた場合はコピーする必要がある。しかし、S3本体ではbucketのコピーはサポートしていない。
以下のスクリプトを作ってみた。copy自体はS3側で直接送信する形になるのである程度高速ではある。
require 'right_aws'
aws_access_key_id, aws_secret_access_key = "key_id", "access_key"
old_bucket_name = 'from-bucket'
new_bucket_name = "to-bucket"
s3 = RightAws::S3.new(aws_access_key_id, aws_secret_access_key)
bucket = s3.bucket(old_bucket_name)
puts "Copy S3 files from '#{old_bucket_name}' to '#{new_bucket_name}'"
total_count = bucket.keys.count
puts "total_count: #{total_count}"
print "Are you sure? (y/N) > "
if gets.strip == 'y'
puts "Start to copy at #{Time.now}"
bucket.keys.each_with_index do |key, i|
print "\r#{i}"
s3.interface.copy(old_bucket_name, key.name, new_bucket_name, key.name)
end
end
アカウントを超えて転送する場合、権限が正しくつかない場合があるのでその対応を行ったパターン
require "rubygems"
require 'right_aws'
require "parallel"
aws_access_key_id, aws_secret_access_key = "xxx", "xxx"
new_bucket_email_address = "xxx@xxxx.com"
old_bucket_name = 'old'
new_bucket_name = "new"
s3 = RightAws::S3.new(aws_access_key_id, aws_secret_access_key)
bucket = RightAws::S3::Bucket.new(s3, old_bucket_name)
puts "Copy S3 files from '#{old_bucket_name}' to '#{new_bucket_name}'"
total_count = bucket.keys.count
puts "total_count: #{total_count}"
print "Are you sure? (y/N) > "
if gets.strip == 'y'
Parallel.each_with_index(bucket.keys, in_processes: 10) do |key, i|
print "\r#{i}: #{key}"
s3.interface.copy(old_bucket_name, key.name, new_bucket_name, key.name, :replace, {'x-amz-grant-full-control' => %!emailAddress="#{new_bucket_email_address}"!, 'x-amz-grant-read' => 'uri=http://acs.amazonaws.com/groups/global/AllUsers'})
end
end