File Transfer using SFTP in Java (JSch)

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/mkyong/.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/mkyong/.ssh/id_rsa
  • Remote public key – ~/.ssh/authorized_keys

  JSch jsch = new JSch();
  jsch.setKnownHosts("/home/mkyong/.ssh/known_hosts");
  jschSession = jsch.getSession(USERNAME, REMOTE_HOST, REMOTE_PORT);

  jsch.addIdentity("/home/mkyong/.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.mkyong.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/mkyong/local/random.txt";
        String remoteFile = "/home/mkyong/remote/afile.txt";

        Session jschSession = null;

        try {

            JSch jsch = new JSch();
            jsch.setKnownHosts("/home/mkyong/.ssh/known_hosts");
            jschSession = jsch.getSession(USERNAME, REMOTE_HOST, REMOTE_PORT);

            // authenticate using private key
            // jsch.addIdentity("/home/mkyong/.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.

Terminal

$ ssh-keyscan -t rsa 1.2.3.4 >> ~/.ssh/known_hosts

3.2 For invalid privatekey, convert the private key to another format.

Terminal

$ ssh-keygen -p -f ~/.ssh/id_rsa -m pem

3.3 For Auth fail, make sure the provided password is correct.

Terminal

com.jcraft.jsch.JSchException: Auth fail
	at com.jcraft.jsch.Session.connect(Session.java:519)
	at com.mkyong.io.howto.SFTPFileTransfer.main(SFTPFileTransfer.java:34)

Download Source Code

$ git clone https://github.com/mkyong/core-java

$ cd java-io

References

20 comments on “File Transfer using SFTP in Java (JSch)

  1. How to change/set remote file permission after transfer in sftp

    Reply
  2. The code works fine when running locally but throws an Unknownhost exception when running an application inside the Kubernetes POD. I did add a known host locally and point to that file with the method setKnownHosts but it doesn’t work inside the POD (even targetting the known host file).

    Do we need to install ssh inside Linux based K8 pod with yum install ssh or JSch is independent of that? If yes, what could be the reason for that?

    Reply
  3. How do we connect if we have the private key as a String value? not in the form of private key file

    Reply
  4. Hello,
    there is any way to limit to use channel.ls but limited to only first 100 files?

    Because if i use channel.ls and have hundred of files, these are locked by that script and i cannot run parallel processes to download simultaneously files.

    Thanks

    Reply
  5. I am successful in using JSch sending a file from local to remote directory but need assistance with sending a mainframe data set where the data set name is surrounded by single quotes. I can send a file to a data set without single quote around the name but not with single quotes around the name and I need to use single quotes.
    private String datasetName = “‘ABC.DE.FGHI.KL001′”;

    Reply
  6. getting this error

    java.lang.ArrayIndexOutOfBoundsException: 20480
        at com.jcraft.jsch.Session.connect(Unknown Source)
        at filetransfer.SFTPFileTransfer.main(SFTPFileTransfer.java:34)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58)
    com.jcraft.jsch.JSchException: Session.connect: java.lang.ArrayIndexOutOfBoundsException: 20480
        at com.jcraft.jsch.Session.connect(Unknown Source)
        at filetransfer.SFTPFileTransfer.main(SFTPFileTransfer.java:34)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58)
    Done

    created jar and running on local machin

    Reply
  7. Hi

    When I am trying to work with Executor service by creating multiple threads some files are not getting uploaded and I am receiving below error. Can you please help me.

    4: 
    at com.jcraft.jsch.ChannelSftp._realpath(ChannelSftp.java:2362)
    at com.jcraft.jsch.ChannelSftp.cd(ChannelSftp.java:342)
    at com.test.filesystemservice.CopyFileTask.run(CopyFileTask.java:45)
    at com.test.filesystemservice.ParallelTasks.lambda$1(ParallelTasks.java:35)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

    Reply
  8. In my case sftp Exception:Algorithm negotiation fail

     JSch js = new JSch();
      Session s = js.getSession(username, hostname, 22);
      s.setPassword(password);
      Properties confignn = new Properties();
      confignn.put(“StrictHostKeyChecking”, “no”);
      s.setConfig(confignn);
      s.connect();

    Reply
  9. Thanks a lot, it was so useful. And as always you explain very clearly. GOD bless you.

    Reply
  10. Good afternoon,

    Would I be able to transfer a directory, its subdirectories and all existing files at once?

    Reply
  11. Jsch supports only one file transfer mode – binary. But how does camel sftp support ascii/binary file transfer modes? Camel sftp also internally uses jsch right?

    Reply
  12. When I give password it works fine, but when I try for SSH public key
    like this — jsch.addIdentity(“~/.ssh/authorized_keys”);

    Error occurred due to com.jcraft.jsch.JSchException: java.io.FileNotFoundException: C:\Users\****\.ssh\authorized_keys (The system cannot find the file specified)

    May I know why its referring to local path instead of remote server

    Reply

Leave a Comment

Your email address will not be published. Required fields are marked *