В моем приложении SpringBoot я использовал Spring Integration для загрузки файлов на удаленный SFTP-сервер. Ниже приведен фрагмент кода, который я использовал для передачи файла на сервер SFTP.
protected String transfer(String downloadDirectory) {
File[] files = new File(downloadDirectory).listFiles();
byte[] payload = null;
String path = null;
try {
path = getSftpPath(downloadDirectory);
for (int i = 0; i < files.length; i++) {
if (files[i].isFile()) {
payload = Files.readAllBytes(Paths.get(files[i].toURI()));
gateway.upload(payload, files[i].getName(), path);
}
}
} catch (Exception e) {
throw new Exception(e);
}
return path;
}
Объявление метода загрузки и MessageHandler выглядит следующим образом
@MessagingGateway(asyncExecutor = "sftpAsync")
public interface UploadGateway {
@Gateway(requestChannel = "toSftpChannel")
void upload(@Payload byte[] file, @Header("filename") String filename, @Header("path") String path);
}
@Bean
@ServiceActivator(inputChannel = "toSftpChannel")
public MessageHandler handler() {
SftpMessageHandler handler = new SftpMessageHandler(sftpSessionFactory());
ExpressionParser expressionParser = new SpelExpressionParser();
handler.setRemoteDirectoryExpression(expressionParser.parseExpression("headers['path']"));
handler.setFileNameGenerator(msg -> (String) msg.getHeaders().get("filename"));
handler.setAutoCreateDirectory(true);
return handler;
}
Он отлично работает для загрузки файлов на удаленный SFTP-сервер. Но после нескольких запусков он начинает показывать
java.lang.OutOfMemoryError: Direct buffer memory
at java.nio.Bits.reserveMemory(Unknown Source)
at java.nio.DirectByteBuffer.<init>(Unknown Source)
at java.nio.ByteBuffer.allocateDirect(Unknown Source)
at sun.nio.ch.Util.getTemporaryDirectBuffer(Unknown Source)
at sun.nio.ch.IOUtil.read(Unknown Source)
at sun.nio.ch.FileChannelImpl.read(Unknown Source)
at sun.nio.ch.ChannelInputStream.read(Unknown Source)
at sun.nio.ch.ChannelInputStream.read(Unknown Source)
at sun.nio.ch.ChannelInputStream.read(Unknown Source)
at java.nio.file.Files.read(Unknown Source)
at java.nio.file.Files.readAllBytes(Unknown Source)
payload = Files.readAllBytes(Paths.get(files[i].toURI())); - это строка, в которой выдается указанное выше сообщение об ошибке.
Насколько я понимаю, я читаю весь файл в байтовый массив, поэтому получаю эту ошибку. Поскольку мне нужно отправить файл целиком в метод загрузки, я применил подход byte [].
Я уже проверял указанные ниже темы.
Byte [] и java.lang.OutOfMemoryError чтение файла по битам
java.lang.OutOfMemoryError: прямая буферная память при вызове Files.readAllBytes
но для метода загрузки нужен весь файл, а не поток байтов или фрагментов данных (поправьте меня, если я ошибаюсь).
Таким образом, любые предложения по устранению вышеуказанной проблемы являются большим подспорьем.
Спасибо.
Вам нужно работать с InputStream вместо массива или всего большого двоичного объекта, который будет находиться в памяти. Это может быть ByteArrayInputStream, FileInputStream и т. д. Изучите документацию java для sftp-адаптера, чтобы узнать, какие интерфейсы доступны.




Замените это:
payload = Files.readAllBytes(Paths.get(files[i].toURI())); gateway.upload(payload, files[i].getName(), path);На это:Path tempFile = Paths.get(files[i].toURI()); gateway.upload(tempFile.toFile());