--
RyanBarrett - 06 Jan 2022 ---+
Using Jsch for SFTP in Java
SSH File Transfer Protocol (also known as Secure File Transfer Protocol or SFTP) is a network protocol to handle file access, file transfer, and file management that relies on SSH. It works by creating a secure connection with a server or file system which it then uses during its operations, providing a greater level of security. Although SFTP may not come up as frequently in testing scenarios compared to other components, the functionality provided by SFTP can often be valuable when working with and testing applications that involve a file system on a server.
Prerequisites
There are several libraries that handle performing SFTP operations in Java. This tutorial focuses on the
Jsch library, which can be added to the project via Maven. You'll need to add the following dependency to the dependencies in your pom.xml file after setting up your project.
You will also want to have an IDE for java development.
<!-- https://mvnrepository.com/artifact/com.jcraft/jsch -->
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.55</version>
</dependency>
From there, you can begin exploring the different operations for SFTP offered by Jsch.
Operations
There are several different operations for Jsch; this tutorial will mostly focus on connections, uploads, and downloads, as these have typically proven the most relevant in testing that required use of SFTP. Look at the examples below for reference on how to perform different SFTP operations using Jsch.
Connecting to a File System
To connect to a file system, you will need to authenticate using either a username and password or a public key. The example below uses password authentication. You will also need known_hosts file, which can be generated with the command "ssh-keyscan -H -t rsa REMOTE_HOSTNAME >> known_hosts".
private ChannelSftp getJschSFTPConnection(String knownHostsPath, String username, String remoteHost, String password) throws JSchException {
JSch jsch = new JSch();
jsch.setKnownHosts(knownHostsPath); //The known hosts file is used as a reference to determine if the server can be trusted generated on command line with ssh-keyscan -H -t rsa REMOTE_HOSTNAME >> known_hosts
Session session = jsch.getSession(username, remoteHost); //Create session
session.setConfig("PreferredAuthentications", "publickey,keyboard-interactive,password"); //Set session config ->used to avoid having to authenticate manually (Kerberos, etc.)
session.setPassword(password); //Set the password
session.connect(); //Connect and open SFTP channel
return (ChannelSftp) session.openChannel("sftp");
}
Once you have an SFTP connection available via JSCH, you can begin performing different SFTP operations using Jsch. You'll be able to use the following command to generate a channel for SFTP commands. All later operations need to be done using an SFTP channel with an active connection.
ChannelSftp channelSftp = getJschSFTPConnection(String knownHostsPath, String username, String remoteHost, String password)
channelSftp.connect();
The connection can later be terminated via the following method.
channelSftp.exit();
Uploading a File
To upload a file, a user will need a path to the local file to upload and a path to a location on the directory to place the file in. Consider the example below:
String localFile = "src/test/resources/TC01.txt";
String remoteDir = "sftp_test/";
channelSftp.put(localFile, remoteDir + "test.txt"); //put() method used to upload files
Note that a new file name will need to be included in the remote directory path when the file is uploaded using the put method..
Downloading a File
To download a file, you will need a remote file path and a local file path as parameters. In this case, the file in the location given via the remote path will be downloaded to the given local file path.
String remoteFile = "sftp_test_results/data.txt";
String localDir = "src/main/resources/";
channelSftp.get(remoteFile, localDir + "result.txt"); //File is downloaded using the get() method
Note that a new file name will need to be included in the local directory path when the file is uploaded using the get method.
Moving a File
To move or rename a file on the server, you will need to include both the old and new file paths as parameters for the rename() method, which will be used to locate, move, and rename the file/directory.
String oldFilePath = "sftp_test_results/data.txt";
String newFilePath = "old_sftp_results/old_data.txt";
channelSftp.rename(oldFilePath, newFilePath);
Deleting a File
The rm() and rmdir() methods can be used to remove files and directories from a server respectively. See the examples below.
String file = "junk.txt";
String directory = "unused_directory";
channelSftp.rm(file); //Removes junk.txt
channelSftp.rmdir(directory); Removes directory named unused_directory
Checking for a File
Jsch does not come with a built in utility for directly checking whether or not a file exists, but certain methods, such as ls() and stat(), can be used in methods to determine whether or not a file exists. Consider the basic example below.
String psth = "test.txt"
SftpATTRS attrs=null;
try {
attrs = channelSftp.stat(path); //Try to get file attributes
} catch (Exception e) {
System.out.println(path+" not found"); //If it fails, catch exception and continue
}
if (attrs != null) {
System.out.println("File exists"); //If attributes is not null, then file was successfully found
return true;
} else {
return false; //Otherwise, file was not found in expected location
}
Resources
Here are some additional helpful resources for using Jsch.