SFTP Client using SSHJ
In this post we are going to create a SFTP Client using the SSHJ library. Compared to JSch, SSHJ has a more clear and simple java API especially for authentication.
All we need to do is import SSHJ dependency.
<dependency>
<groupId>com.hierynomus</groupId>
<artifactId>sshj</artifactId>
<version>0.39.0</version>
</dependency>
Then create a SFTP client: SSHJSftpClient
private interface Action<T> {
T handle(SFTPClient sftpClient) throws Exception;
}
private <T> T doInSftpSession(Action<T> action) throws Exception {
try(SSHClient client = new SSHClient()) {
client.addHostKeyVerifier(new PromiscuousVerifier());
System.out.println("SSHJ CONNECT: ["+host+"] ["+port+"] ["+username+"]");
client.connect(host, port);
client.authPassword(username, password);
try (SFTPClient sftpClient = client.newSFTPClient()) {
System.out.println("SSHJ HANDLE SFTP START");
return action.handle(sftpClient);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println("SSHJ HANDLE SFTP DONE");
}
return null;
}
Create doInSftpSession method, this method has parameter Action (an interface). We will implement an Action interface and override the handle method, the purpose of this method is to perform SFTP commands in an independent session / connection.
Initiate SSHClient: we are not using class variables with singleton instances for SSHClient. I’m not too sure if it is best or bad practice, but when the instance is class variables, we are getting errors after some idle time.
Connect to SFTP Server using password auth, and pass the new SFTPClient to Action.handle method.
After creating doInSftpSession method, we are going to implement list file with and without filter and then return the file names.
List files without filter:
public Collection<String> listFiles(String path) throws Exception {
return doInSftpSession(sftpClient -> {
System.out.println("SSHJ LIST FILE ["+path+"]");
List<RemoteResourceInfo> listFile = sftpClient.ls(path);
System.out.println("SSHJ FILES ["+listFile.stream().map(RemoteResourceInfo::getName).collect(Collectors.joining(",")));
Return listFile.stream().map(RemoteResourceInfo::getName).collect(Collectors.toList());
});
}
Simply call doInSftpSession method, then implement the Action interface as parameter and call sftpClient.ls(path) to get all the RemoteResourceInfo and call getName to get remote filenames.
List files with filter:
public Collection<String> listFiles(String path, String startFileName) throws Exception {
return doInSftpSession(sftpClient -> {
System.out.println("SSHJ LIST FILE ["+path+"]");
List<RemoteResourceInfo> listFile = sftpClient.ls(path, new RemoteResourceFilter() {
@Override
public boolean accept(RemoteResourceInfo resource) {
return resource.getName().startsWith(startFileName);
}
});
System.out.println("SSHJ FILES ["+listFile.stream().map(RemoteResourceInfo::getName).collect(Collectors.joining(","))+"]");
return listFile.stream().map(RemoteResourceInfo::getName).collect(Collectors.toList());
});
}
Above code will return files in path parameters that start with startFileName parameter. Simply call sftpClient.ls(String path, RemoteResourceFilter filter) this method accepts RemoteResourceFilter class that has an accept method to be overridden.
Download File:
Downloading file with resume capability. We are going to check whether files exist on local storage or not. if file exists, download file from SFTP with offset equal to local file’s length.
public void downloadFile(String source, String destination) throws Exception {
doInSftpSession(sftpClient -> {
File localFile = new File(destination);
if (localFile.exists()) {
System.out.println("SSHJ DOWNLOAD FILE FROM "+source+" TO "+destination+" WITH OFFSET: "+localFile.length());
sftpClient.get(source, destination, localFile.length());
} else {
System.out.println("SSHJ DOWNLOAD FILE FROM "+source+" TO "+destination);
sftpClient.get(source, destination);
}
return null;
});
}
Upload File
Uploading a file from the local path to the SFTP server is really simple, all we need to do is call the put method and specify the local path and remote path.
public void uploadFile(String sourceFilePath, String remoteDirPath) throws Exception {
doInSftpSession(sftpClient -> {
System.out.println("SSHJ UPLOAD FILE FROM "+sourceFilePath+" TO "+remoteDirPath);
sftpClient.put(sourceFilePath, remoteDirPath);
return null;
});
}
That's all about creating a SFTP Client using the SSHJ library, hope this helps.
Comments
Post a Comment