This is 2 step solution, download locally then upload to ActiveStorage.

(I couldn’t figure out how to directly write from ftp into AS.)

username = "foo"
password = "p@ss"
host = "exampledomain.com"
uri = URI.parse("ftp://#{username}:#{password}@#{host}/")

Net::FTP.open(uri.host, uri.user, uri.password) do |ftp|
  ftp.chdir('your_directory')
  name_to_images.each do |image, filename|
    image_filename = "#{image}.MAIN.#{filename.split(".").last.downcase}"

    begin
      puts ftp.size(filename)
      tmp = Tempfile.new
      ftp.getbinaryfile(filename, tmp)
      # account has_many_attached :images
      account.images.attach(io: tmp, filename: image_filename)
      sleep(0.1)
    rescue Net::FTPPermError => e
      missing_image = e.message.starts_with?('550')
      if missing_image
        puts "missing_image #{filename}"
        next
      end
      puts e.message
      next
    end
  end
end