Pure java implementation of sftp-jsch

Originality Statement: This article is totally original for the author, please respect the author's labor force. Reprint must indicate the original address.

sftp and ftp

To talk about sftp (SSH File Transfer Protocol), we first need to talk about ftp (File Transfer Protocol). As we all know, ftp is a file transfer protocol, which is based on tcp protocol and can be used to send files. When I first started learning web development, I came into contact with some free cloud space. At that time, I used a ftp tool to upload the project.

sftp and ssh

SFTP is the ftp of security, because it is based on ssh protocol. ssh is a security protocol, which is used for secure connection between different systems or servers. ssh encrypts all data in the process of connection and transmission. So in general, file transfer through ssh protocol is sftp.

So how to use SSH to achieve file transfer? Partners familiar with Linux should be familiar with ssh, because Linux brings SSH (Shh! Actually, I'm not familiar with linux, but I know that Linux has ssh. It was not long before it was loaded and unloaded. Now I find that it will improve a lot. Make sure you have another one to play with!

Unfortunately, ssh is basically based on linux and some client installation software. So in our usual web development, how to use sftp to transfer files? jsch is the solution.

Introduction to jsch

jsch is a pure java implementation of ssh. It's a bit abstract. In general, you're here. Official website down is a jar package. Introducing your project, you can use it to transfer files safely to a server that also has ssh on. (Of course, you need some username and password information from that target server, otherwise gg will do.)

Start using

  • Step 1: First check in the maven central warehouse how to rely on pom, you can point Here.

tip: If you're using other build tools like Gradle, depend on the project in other ways. If you don't use component tools, add jar packages directly to your project.

maven's for this (I'm using the latest version of 0.1.54):

 <!-- https://mvnrepository.com/artifact/com.jcraft/jsch -->
 <dependency>
    <groupId>com.jcraft</groupId>
    <artifactId>jsch</artifactId>
    <version>0.1.54</version>
</dependency>

Add to the pom file and you can proceed to the next step.

  • Step 2: Create a tool class: SFTPUtils.java, which reads as follows
import com.jcraft.jsch.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Properties;

/**
 * SFTP Tool class
 * There are two methods:
 * A sftp channel object is created and returned, through which files can be sent directly.
 * The other is for closing calls and channels.
 */
public class SFTPUtils {
  static private final Logger log = LoggerFactory.getLogger(SFTPUtils.class);

  static private Session session = null;
  static private Channel channel = null;
  static private int timeout = 60000; //Overtime, one minute

  /**
   * Input a channel object
   * @param username User name of the server to be connected remotely
   * @param password The password of the remote server to connect to
   * @param ip Remote server ip
   * @param port ssh service port of remote server
   * @return ChannelSftp Returns a channel instance pointing to the address specified in this channel
   * @throws JSchException
   */
  public static ChannelSftp getChannel(String username, String password, String ip, String port) throws JSchException {
    JSch jsch = new JSch(); // Create JSch objects
    // Get a Session object by user name, host ip, port
    session = jsch.getSession(username, ip, Integer.valueOf(aisle.getServerPort()));
    log.info("Session created...");
    if (password != null) {
      session.setPassword(password); // Setting Password
    }
    Properties config = new Properties();
    config.put("StrictHostKeyChecking", "no");
    session.setConfig(config); // Setting properties for Session objects
    session.setTimeout(timeout); // Setting timeout time
    session.connect(); // Create links through Session
    log.info("Session connected, Opening Channel...");
    channel = session.openChannel("sftp"); // Open SFTP channel
    channel.connect(); // Establishment of SFTP Channel Connection
    log.info("Connected successfully to ip :{}, ftpUsername is :{}, return :{}",
        ip,username, channel);
    return (ChannelSftp) channel;
  }

  /**
   * Close channel and session
   * @throws Exception
   */
  public static void closeChannel() throws Exception {
    if (channel != null) {
      channel.disconnect();
    }
    if (session != null) {
      session.disconnect();
    }
  }
}
  • Step 3: The tool classes have been built, so use them directly - create test classes.
import com.gildata.gup.util.SFTPUtils;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.SftpException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FileInputStream;
import java.util.Vector;

/**
 * sftp Push test class
 */
@Service
public class SftpTest {

  private final Logger log = LoggerFactory.getLogger(SftpPushTest.class);

  /**
   * Test methods for file push.
   * destDirPath Folder paths to be saved by remote servers
   * file  File objects to be pushed locally
   * username User name of remote server
   * password  Password of remote server
   * ip  Remote server ip
   * port Remote server ssh service port
   */
  public void testSftp() throws SftpException {
      // Assumed parameter values
      String dstDirPath = "E:\\target";
      String username = "admin";
      String password = "admin";
      String ip = "127.0.0.1"; 
      String port = 21; 

      ChannelSftp channelSftp = null;
      String dstFilePath; // Target file name (with path), such as: D:\file\file.doc, which should be the path to be saved under the remote target server
      try {
          // 1. Getting channelSftp objects
          channelSftp = SFTPUtils.getChannel(username, password, ip, port);
          // 2. Judging whether the remote path dstDirPath exists (the path of channel configuration)
          try {
              Vector dir = channelSftp.ls(dstDirPath);
              if (dir == null) { // If the path does not exist, create
                  channelSftp.mkdir(dstDirPath);
              }
          } catch (SftpException e) { // If dstDirPath does not exist, an error will be reported, at which point exceptions are caught and dstDirPath paths are created.
              channelSftp.mkdir(dstDirPath); // At this point, create path o throws an exception if it fails to create an error again
              e.printStackTrace();
          }
          // 3. Pushing Documents
          try {
              log.info("send the file : {}", file.getName());
              dstFilePath = dstDirPath + "\\" + file.getName();
              log.info("the file all path is :{}", dstFilePath);
              // Push: dstFilePath - Past file paths (full paths) are transferred using the default override push
              channelSftp.put(new FileInputStream(file), dstFilePath); // jsch trigger push operation method
          }  catch (SftpException e) {
              log.debug("An error occurred during sftp push, send data fail, the target path is :{}", dstDirPath);
              if (log.isDebugEnabled()) {
                  e.printStackTrace();
              }
          }
      }  finally {
          // Handling the matter
          if (channelSftp != null)
              channelSftp.quit();
          try {
              SFTPUtils.closeChannel();
          } catch (Exception e) {
              if (log.isDebugEnabled())
                  e.printStackTrace();
          }
      }
  }

}

By executing the testSftp method, you can transfer the file to the dstDirPath directory of the target server.

Assume that the local path of the file is D: source sftp_learning. ppt. And the target path dstDirPath is: E: target. After the push is executed, the sftp_learning.ppt file will be found in the E: target directory of the remote device whose IP is ip.

Question?!

Unfortunately, Windows does not have its own ssh service like linux. A directory like E: target above clearly indicates that the remote device is a Windows system. In normal development, even if your username, password, port are not mistyped, the program will throw SftpException exception, because you have to target server does not enable ssh service.

How to solve it?

Since the target server has no windows with ssh services, try to configure ssh services under windows.

Generally speaking, servers run under linux, so don't worry about it. This time, the author also encountered this problem because he wanted to test it locally under his own windows. How to configure ssh services under windows is another topic. In this test, I used the Cygwin tool. Specific how to use, a large number of online search. If you read in support of the author, please pay attention to me, I will share Cygwin's use of heart as soon as possible!

That's all about jsch's implementation of sftp transfer file sharing. Hope to help you all! (22:22, OMG)

For more information about Channel Sftp's API methods, see the official website, or Baidu. There are many overloads on put methods. Progress display is also supported.

Keywords: ssh Session sftp Linux

Added by pug on Mon, 15 Jul 2019 03:29:34 +0300