This article shows how to do file transfer from a remote server to the local system and vice versa, using SSH File Transfer Protocol (SFTP) in Java.
P.S Tested with JSch 0.1.55
1. JSch Dependency
pom.xml
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.55</version>
</dependency>
2. File Transfer – JSch Examples
2.1 In JSch, we can use put and get to do file transfer between servers.
We use put to transfer files from a local system to the remote server.
channelSftp.put(localFile, remoteFile);
We use get to download files from a remote server to the local system.
channelSftp.get(remoteFile, localFile)
2.2 Password authentication.
JSch jsch = new JSch();
jsch.setKnownHosts("/home/favtuts/.ssh/known_hosts");
jschSession = jsch.getSession(USERNAME, REMOTE_HOST, REMOTE_PORT);
jschSession.setPassword(PASSWORD);
2.3 Public and private keys authentication, read this Use Public Key Authentication with SSH
- Local private key –
/home/favtuts/.ssh/id_rsa - Remote public key –
~/.ssh/authorized_keys
JSch jsch = new JSch();
jsch.setKnownHosts("/home/favtuts/.ssh/known_hosts");
jschSession = jsch.getSession(USERNAME, REMOTE_HOST, REMOTE_PORT);
jsch.addIdentity("/home/favtuts/.ssh/id_rsa");
2.4 Review this complete JSch example to transfer a file from the local system to a remote server 1.2.3.4, authenticate using an SSH password.
SFTPFileTransfer.java
package com.favtuts.io.howto;
import com.jcraft.jsch.*;
public class SFTPFileTransfer {
private static final String REMOTE_HOST = "1.2.3.4";
private static final String USERNAME = "";
private static final String PASSWORD = "";
private static final int REMOTE_PORT = 22;
private static final int SESSION_TIMEOUT = 10000;
private static final int CHANNEL_TIMEOUT = 5000;
public static void main(String[] args) {
String localFile = "/home/favtuts/local/random.txt";
String remoteFile = "/home/favtuts/remote/afile.txt";
Session jschSession = null;
try {
JSch jsch = new JSch();
jsch.setKnownHosts("/home/favtuts/.ssh/known_hosts");
jschSession = jsch.getSession(USERNAME, REMOTE_HOST, REMOTE_PORT);
// authenticate using private key
// jsch.addIdentity("/home/favtuts/.ssh/id_rsa");
// authenticate using password
jschSession.setPassword(PASSWORD);
// 10 seconds session timeout
jschSession.connect(SESSION_TIMEOUT);
Channel sftp = jschSession.openChannel("sftp");
// 5 seconds timeout
sftp.connect(CHANNEL_TIMEOUT);
ChannelSftp channelSftp = (ChannelSftp) sftp;
// transfer file from local to remote server
channelSftp.put(localFile, remoteFile);
// download file from remote server to local
// channelSftp.get(remoteFile, localFile);
channelSftp.exit();
} catch (JSchException | SftpException e) {
e.printStackTrace();
} finally {
if (jschSession != null) {
jschSession.disconnect();
}
}
System.out.println("Done");
}
}
3. JSch Exceptions
Some common exceptions.
3.1 For UnknownHostKey exception, add the remote IP address into the known_hosts file.
Run the above program, and it throws UnknownHostKey?
com.jcraft.jsch.JSchException: UnknownHostKey: 1.1.1.1. RSA key fingerprint is ::::
at com.jcraft.jsch.Session.checkHost(Session.java:805)
at com.jcraft.jsch.Session.connect(Session.java:345)
at com.jcraft.jsch.Session.connect(Session.java:183)
at com.favtuts.io.howto.SFTPFileTransfer.initJsch(SFTPFileTransfer.java:29)
at com.favtuts.io.howto.SFTPFileTransfer.uploadFileUsingJsch(SFTPFileTransfer.java:35)
at com.favtuts.io.howto.SFTPFileTransfer.main(SFTPFileTransfer.java:16)
To solve it, we can use ssh-keyscan to add the remote IP address or hostname into the ~/.ssh/known_hosts
ssh-keyscan -t rsa <HOST_NAME> >> ~/.ssh/known_hosts
ssh-keyscan -t rsa <IP_ADDRESS_OF_HOST_NAME> >> ~/.ssh/known_hosts
For example,
$ ssh-keyscan -t rsa 1.2.3.4 >> ~/.ssh/known_hosts
# 1.1.1.1:22 SSH-2.0-OpenSSH_7.4p1 Debian-10+deb9u7
3.2 For invalid privatekey, convert the private key to another format.
This Java example tries to use JSch to transfer a file from the local folder to a remote server using public and private keys, instead of a password.
// private key location
jsch.addIdentity("/home/favtuts/.ssh/id_rsa");
It may throws the invalid privatekey exception.
com.jcraft.jsch.JSchException: invalid privatekey: [B@1324409e
at com.jcraft.jsch.KeyPair.load(KeyPair.java:664)
at com.jcraft.jsch.KeyPair.load(KeyPair.java:561)
at com.jcraft.jsch.IdentityFile.newInstance(IdentityFile.java:40)
at com.jcraft.jsch.JSch.addIdentity(JSch.java:406)
at com.jcraft.jsch.JSch.addIdentity(JSch.java:366)
at com.favtuts.io.howto.SFTPFileTransfer.main(SFTPFileTransfer.java:31)
Check the private key, and it looks something like:
$ cat /home/favtuts/.ssh/id_rsa
$ cat /home/favtuts/.ssh/id_rsa
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC...
...
...
...MAECAwQF
-----END OPENSSH PRIVATE KEY-----
Solution
The Jsch seems not to support the above private key format, to solve it, we can use ssh-keygen to convert the private key format to the RSA or pem mode, and the above program works again.
$ ssh-keygen -p -f ~/.ssh/id_rsa -m pem
Recheck the private key content, it should starts with BEGIN RSA.
$ cat /home/mkyong/.ssh/id_rsa
-----BEGIN RSA PRIVATE KEY-----
MIIG4wIBAAK...
...
...
...E428GBDI4
-----END RSA PRIVATE KEY-----
3.3 For Auth fail, make sure the provided password is correct.
com.jcraft.jsch.JSchException: Auth fail
at com.jcraft.jsch.Session.connect(Session.java:519)
at com.favtuts.io.howto.SFTPFileTransfer.main(SFTPFileTransfer.java:34)
Download Source Code
$ git clone https://github.com/favtuts/java-core-tutorials-examples
$ cd java-io/howto