Migrating Cloudinary Accounts
A handy Ruby script if you ever have to migrate buckets for Cloudinary.
Learned this snippet from @cloudinary
The other month we shipped a new product at Bento that enabled users to show pop-ups to their customers to collect email addresses. Awesome, right?
I was so excited to ship it that I accidently shipped it with the wrong Cloudinary account hooked up ... and because that was a development acccount it started to hit limits on the free plan so stopped serving content on those pop-ups. OOPS! 🤦♂️
Running multiple Cloudinary paid accounts is a tad silly so I reached out to support to ask them if they could help. The following is a Ruby script they sent to me that helped me migrate all my content from one account to another all in Ruby.
Hope this helps someone else who is in a pickle!
# Call the Upload API for a file containing filenames or URLs, in parallel
# Applies various upload options
gem 'cloudinary';
require('cloudinary')
require 'csv'
# Account Credentials for destination account
Cloudinary::config_from_url("<CLOUDINARY_URL>")
Cloudinary.config.cloud_name
files_to_upload = []
# Optional: Get the file list from CSV file.
CSV.foreach("test.csv") {
|row| files_to_upload << row[0] # first column has the URLs
}
puts "Uploading to cloud-name: " + Cloudinary::config.cloud_name
puts files_to_upload.size.to_s + " resources total";
puts files_to_upload if files_to_upload.size < 100
puts "Start time: "+ Time.new.inspect
sleep 10; # Leave the output above on the screen for a while before proceeding further
# Process uploads in parallel
transferred_resources = []
threads = []
number_of_threads = 5
chunk_size = files_to_upload.size/number_of_threads
chunks = files_to_upload.each_slice(chunk_size).to_a;0
chunks.each do |res|
threads << Thread.new {
res.each_with_index do |resource,i|
begin
# Decide how to name the new file - in this example, last part of the URL, excluding extension
new_public_id = resource.split("/")[-1].sub(/\.[^.]+\z/, '')
puts new_public_id
puts "#{i}/#{res.length} #{resource} - "+ Time.new.inspect
result = Cloudinary::Uploader.upload(
resource,
:public_id => new_public_id,
:folder => '',
:type => 'upload',
:overwrite => false,
:tags => ["migrated"],
return_error: true);0
puts "#{i}/#{res.length} #{resource} - " + Time.new.inspect
transferred_resources.push(result);0
rescue Exception => e
puts e;
sleep(10); # wait before continuing
end
end
}
end;0
threads.each { |thr| thr.join }
# Displays any error messages
transferred_resources.select{|a| a['error']}
puts "End time: "+ Time.new.inspect
Then, after you've completed the upload, go into your database and gsub the cloud_name and you're done!
Subscribe to my personal updates
Get emails from me about building software, marketing, and things I've learned building products on the web. Occasionally, a quiet announcement or two.