Java实现上传文件到指定服务器指定目录

遇到了此类问题,网上找到一篇文章,基于此,转载此篇文章,如有版本不一致,我遇到的就是自己私服版本不一致,根据示例代码很容易修改,实际代码对upload方法封装了一层,支持文件list上传,在远处桌面开发,就不贴出来了

原文地址 https://www.cnblogs.com/jichi/p/12158537.html

前言需求

使用 freemarker 生成的静态文件,统一存储在某个服务器上。本来一开始打算使用 ftp 实现的,奈何老连接不上,改用 jsch。毕竟有现成的就很舒服,在此介绍给大家。

具体实现

引入的 pom

1
2
3
4
5
6
7
8
9
10
11
<dependency>
<groupId>ch.ethz.ganymed</groupId>
<artifactId>ganymed-ssh2</artifactId>
<version>262</version>
</dependency>

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

建立实体类

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
public class ResultEntity {

private String code;

private String message;

private File file;

public ResultEntity(){}

public ResultEntity(String code, String message, File file) {
super();
this.code = code;
this.message = message;
this.file = file;
}

public String getCode() {
return code;
}

public void setCode(String code) {
this.code = code;
}

public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}

public File getFile() {
return file;
}

public void setFile(File file) {
this.file = file;
}

}
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
public class ScpConnectEntity {
private String userName;
private String passWord;
private String url;
private String targetPath;

public String getTargetPath() {
return targetPath;
}

public void setTargetPath(String targetPath) {
this.targetPath = targetPath;
}

public String getUserName() {
return userName;
}

public void setUserName(String userName) {
this.userName = userName;
}

public String getPassWord() {
return passWord;
}

public void setPassWord(String passWord) {
this.passWord = passWord;
}

public String getUrl() {
return url;
}

public void setUrl(String url) {
this.url = url;
}

}

建立文件上传工具类

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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
@Configuration
public class FileUploadUtil {

@Value("${remoteServer.url}")
private String url;

@Value("${remoteServer.password}")
private String passWord;

@Value("${remoteServer.username}")
private String userName;

@Async
public ResultEntity uploadFile(File file, String targetPath, String remoteFileName) throws Exception{
ScpConnectEntity scpConnectEntity=new ScpConnectEntity();
scpConnectEntity.setTargetPath(targetPath);
scpConnectEntity.setUrl(url);
scpConnectEntity.setPassWord(passWord);
scpConnectEntity.setUserName(userName);

String code = null;
String message = null;
try {
if (file == null || !file.exists()) {
throw new IllegalArgumentException("请确保上传文件不为空且存在!");
}
if(remoteFileName==null || "".equals(remoteFileName.trim())){
throw new IllegalArgumentException("远程服务器新建文件名不能为空!");
}
remoteUploadFile(scpConnectEntity, file, remoteFileName);
code = "ok";
message = remoteFileName;
} catch (IllegalArgumentException e) {
code = "Exception";
message = e.getMessage();
} catch (JSchException e) {
code = "Exception";
message = e.getMessage();
} catch (IOException e) {
code = "Exception";
message = e.getMessage();
} catch (Exception e) {
throw e;
} catch (Error e) {
code = "Error";
message = e.getMessage();
}
return new ResultEntity(code, message, null);
}


private void remoteUploadFile(ScpConnectEntity scpConnectEntity, File file,
String remoteFileName) throws JSchException, IOException {

Connection connection = null;
ch.ethz.ssh2.Session session = null;
SCPOutputStream scpo = null;
FileInputStream fis = null;

try {
createDir(scpConnectEntity);
}catch (JSchException e) {
throw e;
}

try {
connection = new Connection(scpConnectEntity.getUrl());
connection.connect();

if(!connection.authenticateWithPassword(scpConnectEntity.getUserName(),scpConnectEntity.getPassWord())){
throw new RuntimeException("SSH连接服务器失败");
}
session = connection.openSession();

SCPClient scpClient = connection.createSCPClient();

scpo = scpClient.put(remoteFileName, file.length(), scpConnectEntity.getTargetPath(), "0666");
fis = new FileInputStream(file);

byte[] buf = new byte[1024];
int hasMore = fis.read(buf);

while(hasMore != -1){
scpo.write(buf);
hasMore = fis.read(buf);
}
} catch (IOException e) {
throw new IOException("SSH上传文件至服务器出错"+e.getMessage());
}finally {
if(null != fis){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(null != scpo){
try {
scpo.flush();
// scpo.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(null != session){
session.close();
}
if(null != connection){
connection.close();
}
}
}


private boolean createDir(ScpConnectEntity scpConnectEntity ) throws JSchException {

JSch jsch = new JSch();
com.jcraft.jsch.Session sshSession = null;
Channel channel= null;
try {
sshSession = jsch.getSession(scpConnectEntity.getUserName(), scpConnectEntity.getUrl(), 22);
sshSession.setPassword(scpConnectEntity.getPassWord());
sshSession.setConfig("StrictHostKeyChecking", "no");
sshSession.connect();
channel = sshSession.openChannel("sftp");
channel.connect();
} catch (JSchException e) {
e.printStackTrace();
throw new JSchException("SFTP连接服务器失败"+e.getMessage());
}
ChannelSftp channelSftp=(ChannelSftp) channel;
if (isDirExist(scpConnectEntity.getTargetPath(),channelSftp)) {
channel.disconnect();
channelSftp.disconnect();
sshSession.disconnect();
return true;
}else {
String pathArry[] = scpConnectEntity.getTargetPath().split("/");
StringBuffer filePath=new StringBuffer("/");
for (String path : pathArry) {
if (path.equals("")) {
continue;
}
filePath.append(path + "/");
try {
if (isDirExist(filePath.toString(),channelSftp)) {
channelSftp.cd(filePath.toString());
} else {
// 建立目录
channelSftp.mkdir(filePath.toString());
// 进入并设置为当前目录
channelSftp.cd(filePath.toString());
}
} catch (SftpException e) {
e.printStackTrace();
throw new JSchException("SFTP无法正常操作服务器"+e.getMessage());
}
}
}
channel.disconnect();
channelSftp.disconnect();
sshSession.disconnect();
return true;
}

private boolean isDirExist(String directory,ChannelSftp channelSftp) {
boolean isDirExistFlag = false;
try {
SftpATTRS sftpATTRS = channelSftp.lstat(directory);
isDirExistFlag = true;
return sftpATTRS.isDir();
} catch (Exception e) {
if (e.getMessage().toLowerCase().equals("no such file")) {
isDirExistFlag = false;
}
}
return isDirExistFlag;
}
}

属性我都写在 Spring 的配置文件里面了。将这个类托管给 spring 容器。
如果在普通类里面使用这个类,就需要看一下上篇博客了。哈哈。

总结

在我们使用的时候,主要调 uploadFile 这个方法即可。传递 File 文件,目标路径及文件名称。