Spring Boot SFTP File Transfer using JSch Java Library

Tags: Java Spring Boot SFTP FTP JSch File Transfer

Overview

In this post we will show you how to transfer files from a local host to a remote server and download files from a remote server to local host via SFTP in Spring Boot applications. In order to transfer files via SFTP in Java applications we also explore the JSch library.

Table of contents

  1. Creating Spring Boot Project with Spring Tool Suite on Eclipse
  2. Add JSch Java library to Gradle or Maven project
  3. Create File Transfer Service interface
  4. Implement File Transfer Service class
  5. Add SFTP configurations to application.properties
  6. Test your code
  7. Final application
  8. Download Source Code

Creating Spring Boot Project with Spring Tool Suite on Eclipse

From Spring Tool Suite IDE select menu File -> New -> Spring Starter Project.

On the New Spring Starter Project popup input new project spring-boot-sftp information as following screenshot.

Creating Spring Boot Project with Spring Tool Suite on Eclipse

Add JSch Java library to Gradle or Maven project

In order to transfer files via SFTP we will use JSch (or Java Secure Channel) library which is a pure Java implementation of SSH2.

For more information about the library you can visit JSch home page at www.jcraft.com/jsch

Add the following dependency to your build.gradle file.

compile group: 'com.jcraft', name: 'jsch', version: '0.1.55'

Or use the following XML to add dependency if you are using Maven build for your project.

<dependency>
    <groupId>com.jcraft</groupId>
    <artifactId>jsch</artifactId>
    <version>0.1.55</version>
</dependency>

Create File Transfer Service interface

Create new package named dev.simplesolution.sftp.service, and add new interface named FileTransferService to this package with source code as following

package dev.simplesolution.sftp.service;

public interface FileTransferService {
	
	boolean uploadFile(String localFilePath, String remoteFilePath);
	
	boolean downloadFile(String localFilePath, String remoteFilePath);

}

Implement File Transfer Service class

Create a new package named dev.simplesolution.sftp.service.impl, and add a class named FileTransferServiceImpl to this new package.

package dev.simplesolution.sftp.service.impl;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;

import dev.simplesolution.sftp.service.FileTransferService;

@Service
public class FileTransferServiceImpl implements FileTransferService {

	private Logger logger = LoggerFactory.getLogger(FileTransferServiceImpl.class);
	
	@Value("${sftp.host}")
	private String host;
	
	@Value("${sftp.port}")
	private Integer port;
	
	@Value("${sftp.username}")
	private String username;
	
	@Value("${sftp.password}")
	private String password;
	
	@Value("${sftp.sessionTimeout}")
	private Integer sessionTimeout;
	
	@Value("${sftp.channelTimeout}")
	private Integer channelTimeout;
	
	@Override
	public boolean uploadFile(String localFilePath, String remoteFilePath) {
		ChannelSftp channelSftp = createChannelSftp();
		try {
			channelSftp.put(localFilePath, remoteFilePath);
			return true;
		} catch(SftpException ex) {
			logger.error("Error upload file", ex);
		} finally {
			disconnectChannelSftp(channelSftp);
		}
		
		return false;
	}

	@Override
	public boolean downloadFile(String localFilePath, String remoteFilePath) {
		ChannelSftp channelSftp = createChannelSftp();
		OutputStream outputStream;
		try {
			File file = new File(localFilePath);
			outputStream = new FileOutputStream(file);
			channelSftp.get(remoteFilePath, outputStream);
			file.createNewFile();
			return true;
		} catch(SftpException | IOException ex) {
			logger.error("Error download file", ex);
		} finally {
			disconnectChannelSftp(channelSftp);
		}
		
		return false;
	}
	
	private ChannelSftp createChannelSftp() {
		try {
			JSch jSch = new JSch();
			Session session = jSch.getSession(username, host, port);
			session.setConfig("StrictHostKeyChecking", "no");
			session.setPassword(password);
			session.connect(sessionTimeout);
			Channel channel = session.openChannel("sftp");
			channel.connect(channelTimeout);
			return (ChannelSftp) channel;
		} catch(JSchException ex) {
			logger.error("Create ChannelSftp error", ex);
		}
		
		return null;
	}
	
	private void disconnectChannelSftp(ChannelSftp channelSftp) {
		try {
			if( channelSftp == null) 
				return;
			
			if(channelSftp.isConnected()) 
				channelSftp.disconnect();
			
			if(channelSftp.getSession() != null) 
				channelSftp.getSession().disconnect();
			
		} catch(Exception ex) {
			logger.error("SFTP disconnect error", ex);
		}
	}
	
}

Add SFTP configurations to application.properties

Add following configurations to properties file at \spring-boot-sftp\src\main\resources\application.properties

sftp.host=127.0.0.1
sftp.port=22
sftp.username=user
sftp.password=password
sftp.sessionTimeout=15000
sftp.channelTimeout=15000

Test your code

Create TestSftpFileTransfer as the following code to use your file transfer service implementation above.

package dev.simplesolution.sftp;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import dev.simplesolution.sftp.service.FileTransferService;

@Component
public class TestSftpFileTransfer implements CommandLineRunner {

	@Autowired
	private FileTransferService fileTransferService;
	
	private Logger logger = LoggerFactory.getLogger(TestSftpFileTransfer.class);
	
	@Override
	public void run(String... args) throws Exception {
		logger.info("Start download file");
		boolean isDownloaded = fileTransferService.downloadFile("/home/simplesolution/readme.txt", "/readme.txt");
		logger.info("Download result: " + String.valueOf(isDownloaded));
		
        logger.info("Start upload file");
		boolean isUploaded = fileTransferService.uploadFile("/home/simplesolution/readme.txt", "/readme2.txt");
		logger.info("Upload result: " + String.valueOf(isUploaded));
	}

}

Final application

After steps above your project will be as the screenshot below.

Spring Boot SFTP File Transfer using JSch Java Library final result

Run project to see result in log console.

Spring Boot SFTP File Transfer using JSch Java Library final result

Download Source Code

The source code in this article can be found at: github.com/simplesolutiondev/spring-boot-sftp

or clone at:

git clone https://github.com/simplesolutiondev/spring-boot-sftp.git

or download at:

Download Source Code

Happy Coding 😊