Вы не можете просто загрузить весь файл в память, как здесь:
byte fileContent[] = new byte[(int) file.length()];
fin.read(fileContent);
Вместо этого загрузите файл по частям и закодируйте его по частям. Base64 - это простая кодировка, достаточно загрузить 3 байта и кодировать их одновременно (это даст 4 байта после кодирования). Из соображений производительности рассмотрим загрузку, кратную 3 байтам, например, 3000 байтов - должно быть просто отлично. Также рассмотрите возможность буферизации входного файла.
Пример:
byte fileContent[] = new byte[3000];
try (FileInputStream fin = new FileInputStream(file)) {
while(fin.read(fileContent) >= 0) {
Base64.encodeBase64(fileContent);
}
}
Обратите внимание, что вы не можете просто добавить результаты массива Base64.encodeBase64()
в encoded
байт. На самом деле, он не загружает файл, а кодирует его в Base64, вызывая проблему нехватки памяти. Это понятно, потому что версия Base64 больше (и у вас уже есть файл, занимающий много памяти).
Попробуйте изменить свой метод на:
public void encode(File file, OutputStream base64OutputStream)
и отправку данных в кодировке Base64 непосредственно в base64OutputStream
вместо их возврата.
ОБНОВЛЕНИЕ: Благодаря @ StephenC я разработал гораздо более простую версию:
public void encode(File file, OutputStream base64OutputStream) {
InputStream is = new FileInputStream(file);
OutputStream out = new Base64OutputStream(base64OutputStream)
IOUtils.copy(is, out);
is.close();
out.close();
}
Используется Base64OutputStream
, который переводит ввод в Base64 на лету и IOUtils
класс из Apache Commons IO .
Примечание: вы должны явно закрыть FileInputStream
и Base64OutputStream
, чтобы напечатать =
, если требуется, но буферизация обрабатывается IOUtils.copy()
.