The main reason I'm writing this blog post now is the struggle I've been through, when getting my Rails API to work with S3. The idea is to receive an image (through the API), in Base64 format, convert it to an image and store it locally (temporary) and upload it to S3. Sounds pretty easy, huh?
To start off, we'll add a few gems to our Gemfile:
gem 'carrierwave' 
gem 'carrierwave-base64' 
gem 'fog'
gem 'figaro'
gem 'unf'
Once you configure CarrierWave and CarrierWave-Base64, as well as fog, the next step is to process the received image and upload it to S3. Add the following methods in your controller:
def split_base64(uri_str)
		  if uri_str.match(%r{^data:(.*?);(.*?),(.*)$})
		    uri = Hash.new
		    uri[:type] = $1 # "image/gif"
		    uri[:encoder] = $2 # "base64"
		    uri[:data] = $3 # data string
		    uri[:extension] = $1.split('/')[1] # "gif"
		    return uri
		  else
		    return nil
		  end
end
def convert_data_uri_to_upload(obj_hash)
		  if obj_hash[:image_url].try(:match, %r{^data:(.*?);(.*?),(.*)$})
		    image_data = split_base64(obj_hash[:image_url])
		    image_data_string = image_data[:data]
		    image_data_binary = Base64.decode64(image_data_string)
		    temp_img_file = Tempfile.new("")
		    temp_img_file.binmode
		    temp_img_file << image_data_binary
		    temp_img_file.rewind
		    img_params = {:filename => "image.#{image_data[:extension]}", :type => image_data[:type], :tempfile => temp_img_file}
		    uploaded_file = ActionDispatch::Http::UploadedFile.new(img_params)
		    obj_hash[:image] = uploaded_file
		    obj_hash.delete(:image_url)
		  end
	return obj_hash    
endRequest example:
{
 "user":{
    	 "name": "John Doe",
     	 "image_url": "data:image/gif;base64,R0lGODlhAQABAJEAAAAAAP////8AAP///yH5BAEAAAMALAAAAAABAAEAAAICVAEAOw=="
 		}   
}The image_url parameter should contain the Base64-encoded image, in the format above.
Next, in your controller's create method:
def create
		@user = User.new(convert_data_uri_to_upload(user_params))
		if @user.save
			render status: 200, json: {
				message: "Successfully added user with ID: " + @user.id.to_s,
				image_url: @user.image_url
			}
		else
			render status: 422, json:{
				errors: @user.errors
			}.to_json
		end
endLastly, in Fog.rb:
CarrierWave.configure do |config|
	
  config.fog_credentials = {
    :provider               => "AWS",
    :region                 => ENV['AWS_REGION'],
    :aws_access_key_id      => ENV['AWS_ACCESS_KEY_ID'],
    :aws_secret_access_key  => ENV['AWS_SECRET_ACCESS_KEY']
  }
  if Rails.env.production?  
  	config.root = Rails.root.join('tmp')
  	config.cache_dir = "#{Rails.root}/tmp/uploads"
  end
  config.fog_directory  = ENV['AWS_BUCKET']
  config.fog_public     = false
end
Make sure you set the correct AWS Keys, Region and Permissions (I got stuck on that for a long time).
If everything went perfect, you should see something similar:
{
	"message": "Successfully added user with ID: 1",
	"image_url": "https://long-ass-link-to-image"
}
This entire process could be pretty catchy, so pay attention to every little detail as it could make a significant difference. If you have any questions, please don't hesitate to contact me or leave a comment in the section below. I'll be more than happy to help you!