Java 代码之 Ftp/Sftp

sftp

引入包

1
2
3
4
5
6
7
<!-- jsch : begin -->
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.51</version>
</dependency>
<!-- jsch : end -->

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
public class SftpHelp {

static Session session = null;
static ChannelSftp channelSftp = null;

public static void loginSftpServer(String host, Integer port, String username, String password, Integer timeout) {
JSch jsch = new JSch();
String msg = null;
try {
session = Objects.requireNonNull(jsch.getSession(username, host, port),
"无法通过 sftp 与服务器建立链接,请检查主机名[host=%s]和用户名[username=%s]是否正确");

session.setPassword(password);
session.setTimeout(timeout);
// 其他 kv 配置项
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);

session.connect();
// 打开 SFTP 通道,并建立连接
channelSftp = (ChannelSftp)session.openChannel("sftp");
channelSftp.connect();

// 设置命令传输编码
// String fileEncoding = System.getProperty("file.encoding");
// channelSftp.setFilenameEncoding(fileEncoding);
} catch (JSchException e) {
msg = formatExceptionMsg(e, host, port, username);
throw new RuntimeException(msg);
}
}

private static String formatExceptionMsg(JSchException e, String host, Integer port, String username) {
String msg = null;
String loginInfo = String.format("host = %s, username = %s, port = %s", host, username, port);
if (null != e.getCause()) {
String unknownHostException = "java.net.UnknownHostException: " + host;
String illegalArgumentException = "java.lang.IllegalArgumentException: port out of range:" + port;
String wrongPort = "java.net.ConnectException: Connection refused";

String cause = e.getCause().toString();
if (unknownHostException.equals(cause)) {
msg = String.format("请确认 sftp 服务器地址是否正确,无法连接到地址为: [%s] 的 sftp 服务器", host);
} else if (illegalArgumentException.equals(cause) || wrongPort.equals(cause)) {
msg = String.format("请确认连接 sftp 服务器端口是否正确,错误的端口: [%s] ", port);
}
} else {
String originalMsg = e.getMessage();
String msgDetail = null;
if ("Auth fail".equals(originalMsg)) {
msgDetail = "用户名或密码错误";
} else {
msgDetail = originalMsg;
}
msg = String.format("与 sftp 服务器建立连接失败,连接信息为 [%s],错误原因为: [%s].", loginInfo, msgDetail);
}
return msg;
}

public static void logoutSftpServer() {
if (channelSftp != null) {
channelSftp.disconnect();
}
if (session != null) {
session.disconnect();
}
}

public static boolean fileExist(String filePath) throws SftpException {
SftpATTRS sftpATTRS = channelSftp.lstat(filePath);
return exist(filePath, () -> sftpATTRS.getSize() >= 0);
}

public static boolean dirExist(String filePath) throws SftpException {
return exist(filePath, channelSftp.lstat(filePath)::isDir);
}

public static boolean isSymbolicLink(String filePath) throws SftpException {
return exist(filePath, channelSftp.lstat(filePath)::isLink);
}

private static boolean exist(String filePath, Supplier<Boolean> s) {
String msg = null;
try {
return s.get();
} catch (Exception e) {
if (e.getMessage().toLowerCase().equals("no such file")) {
msg = String.format("请确认您的配置项 path:[%s] 存在,且配置的用户有权限读取.", filePath);
throw new RuntimeException(msg);
} else {
msg = String.format("获取文件: [%s] 属性时发生I/O异常,请确认与 sftp 服务器的连接正常.", filePath);
throw new RuntimeException(msg);
}
}
}
}