Наиболее эффективным является запись InputStream (который не является атрибутом ByteArrayInputStream).
Просто потому, что каждый байт байта [] потребляет ровно один байт памяти JVM, и каждый символ строки поглощает это количество байтов из памяти JVM, которое символ занимает в пространстве. Итак, представьте, что у вас есть 128 МБ доступной памяти кучи, а «огромный» текстовый/обычный файл имеет размер 1,28 МБ, и 100 пользователей одновременно запрашивают файл, а затем ваше приложение выйдет из строя с помощью OutOfMemoryError. Не очень профессионально.
Имейте «огромные» данные где-нибудь в базе данных или в файловой системе диска и получайте их как InputStream «по умолчанию» (т. Е. Из базы данных с помощью ResultSet # getBinaryStream() или с диска FileInputStream) и напишите к OutputStream через байтовый буфер и/или BufferedInputStream/BufferedOutputStream.
Пример такого сервлета можно найти here.
Удачи.