In my SpringBoot application, I have used Spring Integration for uploading files to a remote SFTP server.
Below is the code snippet I have used to transfer file to SFTP server.
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;
}
The upload method declaration and MessageHandler is as follows
@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;
}
It works fine for uploading files to a remote SFTP server. But after couple of execution, it starts showing
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()));
is the line where it throws the above error message.
As per my understanding, I am reading entire file into byte array, hence I am getting this error. Since I need entire file to send to upload method ,I have followed byte[] approach.
I already checked below mentioned threads.
Byte[] and java.lang.OutOfMemoryError reading file by bits
java.lang.OutOfMemoryError: Direct buffer memory when invoking Files.readAllBytes
but the upload method need entire file instead of stream of bytes or chunks of data (correct me if i am wrong).
So,any suggestions to avoid above issue is great help.
Thanks.