После долгих исследований и головокружения я прочитал исходный код метода putbinaryfile, чтобы найти обходной путь для ограничения putbinaryfile. Вот рабочий код, замените эту строку
ftp.putbinaryfile(file.read, File.basename(file.original_filename))
с
ftp.storbinary("STOR " + file.original_filename, StringIO.new(file.read), Net::FTP::DEFAULT_BLOCKSIZE)
И если вам интересно, STOR - это необработанная команда FTP, да, до этого дошло. Я довольно удивлен, что этот сценарий не так легко обрабатывается стандартными библиотеками Ruby, и, конечно, не было очевидно, что нужно сделать.
А если ваше приложение на Heroku, добавьте эту строку
ftp.passive = true
Настройка брандмауэра Heroku не разрешает активный режим FTP, также убедитесь, что ваш FTP-сервер поддерживает пассивный режим.