使用的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等,大家可以自行探索。