使用的jar包:

1 <dependency>
2     <groupId>com.jcraft</groupId>
3     <artifactId>jsch</artifactId>
4     <version>0.1.54</version>
5 </dependency>

文件上传也可以使用scp,但是最后实现发现scp特别困难,而且只能实现上传这一个功能。如果要实现文件的删除则需要使用其他命令。

而sftp则是建立一个ssh通道,然后可以很方便的在通道内执行一系列命令,如put, get, rm, mkdir, rmdir,从而可以方便的管理远程服务器的文件。

下面介绍下Java实现。

首先我们创建一个pojo,将所有的账号信息及远程服务器信息都封装一下。

1 package com.snow.sftp;
 2 
 3 import lombok.Data;
 4 
 5 @Data
 6 public class SftpAuthority {
 7     private String host;         // 服务器ip或者主机名
 8     private int port;            // sftp端口
 9     private String user;         // sftp使用的用户
10     private String password;     // 账户密码
11     private String privateKey;   // 私钥文件名
12     private String passphrase;   // 私钥密钥
13 
14     public SftpAuthority(String user, String host, int port) {
15         this.host = host;
16         this.port = port;
17         this.user = user;
18     }
19 }

在建立sftp通道过程中我们可以选择使用用户名密码的方式,也可以选择使用私钥(私钥可以有密钥)的方式。

建立一个service interface

1 package com.snow.sftp;
 2 
 3 public interface SftpService {
 4 
 5     void createChannel(SftpAuthority sftpAuthority);
 6 
 7     void closeChannel();
 8 
 9     boolean uploadFile(SftpAuthority sftpAuthority, String src, String dst);
10 
11     boolean removeFile(SftpAuthority sftpAuthority, String dst);
12 
13 }

具体实现:

1 package com.snow.sftp;
  2 
  3 import com.jcraft.jsch.Channel;
  4 import com.jcraft.jsch.ChannelSftp;
  5 import com.jcraft.jsch.JSch;
  6 import com.jcraft.jsch.JSchException;
  7 import com.jcraft.jsch.Session;
  8 import com.jcraft.jsch.SftpException;
  9 import lombok.extern.slf4j.Slf4j;
 10 import org.springframework.stereotype.Service;
 11 
 12 import java.util.Properties;
 13 
 14 @Slf4j
 15 @Service(value = "sftpService")
 16 public class SftpServiceImpl implements SftpService {
 17 
 18     private Session session;
 19     private Channel channel;
 20     private ChannelSftp channelSftp;
 21 
 22     @Override
 23     public void createChannel(SftpAuthority sftpAuthority) {
 24         try {
 25             JSch jSch = new JSch();
 26             session = jSch.getSession(sftpAuthority.getUser(), sftpAuthority.getHost(), sftpAuthority.getPort());
 27 
 28             if (sftpAuthority.getPassword() != null) {
 29                 // 使用用户名密码创建SSH
 30                 session.setPassword(sftpAuthority.getPassword());
 31             } else if (sftpAuthority.getPrivateKey() != null) {
 32                 // 使用公私钥创建SSH
 33                 jSch.addIdentity(sftpAuthority.getPrivateKey(), sftpAuthority.getPassphrase());
 34             }
 35 
 36             Properties properties = new Properties();
 37             properties.put("StrictHostKeyChecking", "no");  // 主动接收ECDSA key fingerprint,不进行HostKeyChecking
 38             session.setConfig(properties);
 39             session.setTimeout(0);  // 设置超时时间为无穷大
 40             session.connect(); // 通过session建立连接
 41 
 42             channel = session.openChannel("sftp"); // 打开SFTP通道
 43             channel.connect();
 44             channelSftp = (ChannelSftp) channel;
 45         } catch (JSchException e) {
 46             log.error("create sftp channel failed!", e);
 47         }
 48     }
 49 
 50     @Override
 51     public void closeChannel() {
 52         if (channel != null) {
 53             channel.disconnect();
 54         }
 55 
 56         if (session != null) {
 57             session.disconnect();
 58         }
 59     }
 60 
 61     @Override
 62     public boolean uploadFile(SftpAuthority sftpAuthority, String src, String dst) {
 63         if (channelSftp == null) {
 64             log.warn("need create channelSftp before upload file");
 65             return false;
 66         }
 67 
 68         if (channelSftp.isClosed()) {
 69             createChannel(sftpAuthority); // 如果被关闭则应重新创建
 70         }
 71 
 72         try {
 73             channelSftp.put(src, dst, ChannelSftp.OVERWRITE);
 74             log.info("sftp upload file success! src: {}, dst: {}", src, dst);
 75             return true;
 76         } catch (SftpException e) {
 77             log.error("sftp upload file failed! src: {}, dst: {}", src, dst, e);
 78             return false;
 79         }
 80     }
 81 
 82     @Override
 83     public boolean removeFile(SftpAuthority sftpAuthority, String dst) {
 84         if (channelSftp == null) {
 85             log.warn("need create channelSftp before remove file");
 86             return false;
 87         }
 88 
 89         if (channelSftp.isClosed()) {
 90             createChannel(sftpAuthority); // 如果被关闭则应重新创建
 91         }
 92 
 93         try {
 94             channelSftp.rm(dst);
 95             log.info("sftp remove file success! dst: {}", dst);
 96             return true;
 97         } catch (SftpException e) {
 98             log.error("sftp remove file failed! dst: {}", dst, e);
 99             return false;
100         }
101     }
102 
103 }

调用示例:

1 package com.snow.sftp;
 2 
 3 import org.springframework.context.ApplicationContext;
 4 import org.springframework.context.support.ClassPathXmlApplicationContext;
 5 
 6 public class TestSftp {
 7 
 8     public static void main(String[] args) {
 9         ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"sftp-application-context.xml"});
10 
11         // 用户名密码方式
12         SftpService sftpService = context.getBean(SftpService.class);
13         SftpAuthority sftpAuthority = new SftpAuthority("user", "ip or host", port);
14         sftpAuthority.setPassword("user password");
15 
16         sftpService.createChannel(sftpAuthority);
17         sftpService.uploadFile(sftpAuthority, "/home/snow/test/test.png", "/user/testaaa.png");
18         sftpService.removeFile(sftpAuthority, "/user/testaaa.png");
19         sftpService.closeChannel();
20 
21         // 公私钥方式
22         sftpAuthority = new SftpAuthority("user", "ip or host", port);
23         sftpAuthority.setPrivateKey("your private key full path");
24         sftpAuthority.setPassphrase("private key passphrase");
25         sftpService.createChannel(sftpAuthority);
26         sftpService.uploadFile(sftpAuthority, "/home/snow/test/test.png", "/user/testaaa.png");
27         sftpService.removeFile(sftpAuthority, "/user/testaaa.png");
28         sftpService.closeChannel();
29     }
30 
31 }

除了本文介绍的put和rm操作以外,channelSftp还有很多其它的操作,比如get, mkdir, lcd, rename, rmdir, ls, lstat等,大家可以自行探索。