1、使用commons-net连接ftp报错,如下所示:
1 org.apache.commons.net.MalformedServerReplyException: Could not parse response code.
2 Server Reply: SSH-2.0-SSH
3 at org.apache.commons.net.ftp.FTP.__getReply(FTP.java:344)
4 at org.apache.commons.net.ftp.FTP.__getReply(FTP.java:300)
5 at org.apache.commons.net.ftp.FTP._connectAction_(FTP.java:438)
6 at org.apache.commons.net.ftp.FTPClient._connectAction_(FTPClient.java:962)
7 at org.apache.commons.net.ftp.FTPClient._connectAction_(FTPClient.java:950)
8 at org.apache.commons.net.SocketClient._connect(SocketClient.java:244)
9 at org.apache.commons.net.SocketClient.connect(SocketClient.java:202)
10 at com.fline.security.adaptation.utils.FtpUtils.uploadFile(FtpUtils.java:63)
11 at com.fline.security.adaptation.utils.FtpUtils.main(FtpUtils.java:29)
其中,使用的commons-net的maven依赖,如下所示:
1 <!-- https://mvnrepository.com/artifact/commons-net/commons-net -->
2 <dependency>
3 <groupId>commons-net</groupId>
4 <artifactId>commons-net</artifactId>
5 <version>3.6</version>
6 </dependency>
案例代码,参考:https://blog.csdn.net/tengdazhang770960436/article/details/43237369,如下所示:
1 package com.fline.security.adaptation.utils;
2
3 import java.io.File;
4 import java.io.FileInputStream;
5 import java.io.FileOutputStream;
6 import java.io.IOException;
7 import java.io.InputStream;
8 import java.io.OutputStream;
9
10 import org.apache.commons.net.ftp.FTPClient;
11 import org.apache.commons.net.ftp.FTPFile;
12 import org.apache.commons.net.ftp.FTPReply;
13
14 public class FtpUtils {
15
16 public static void main(String[] args) throws Exception {
17
18 // // =======上传测试============
19 String localFile = "C:\\Users\\bhlgo\\Downloads\\中国.txt";
20
21 String url = "ip地址";
22 int port = 端口号;
23 String username = "账号";
24 String password = "密码";
25 String path = "目录";
26 String filename = "中国.txt";
27 InputStream input = new FileInputStream(new File(localFile));
28
29 uploadFile(url, port, username, password, path, filename, input);
30 // // =======上传测试============
31
32 // =======下载测试============
33 // String localPath = "D:\\";
34 // String url = "192.168.120.133";
35 // int port = 21;
36 // String username ="ftpuser";
37 // String password ="ftpuser";
38 // String remotePath ="/data/admftp/kw";
39 // String fileName = "test.txt";
40 // downFile(url, port, username, password, remotePath, fileName, localPath);
41 // =======下载测试============
42
43 }
44
45 /**
46 * Description: 向FTP服务器上传文件
47 *
48 * @param url FTP服务器 hostname
49 * @param port FTP服务器端口 默认端 21
50 * @param username FTP登录账号
51 * @param password FTP登录密码
52 * @param path FTP服务器保存目录
53 * @param filename 上传到FTP服务器上的文件名
54 * @param input 输入流
55 * @return 成功返回true,否则返回false
56 */
57 public static boolean uploadFile(String url, int port, String username, String password, String path,
58 String filename, InputStream input) {
59 boolean success = false;
60 FTPClient ftp = new FTPClient();
61 try {
62 int reply;
63 ftp.connect(url, port);// 连接FTP服务器
64 // ftp.connect(url);//连接FTP服务器
65 // 如果采用默认端口,可以使用ftp.connect(url)的方式直接连接FTP服务器
66 ftp.login(username, password);// 登录
67 // ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
68 // ftp.setControlEncoding("GBK");
69 reply = ftp.getReplyCode();
70 if (!FTPReply.isPositiveCompletion(reply)) {
71 ftp.disconnect();
72 return success;
73 }
74 ftp.changeWorkingDirectory(path);
75 // 设置文件名上传的编码格式为 utf-8
76 ftp.storeFile(new String(filename.getBytes("utf-8"), "iso-8859-1"), input);
77
78 input.close();
79 ftp.logout();
80 success = true;
81 } catch (IOException e) {
82 e.printStackTrace();
83 } finally {
84 if (ftp.isConnected()) {
85 try {
86 ftp.disconnect();
87 } catch (IOException ioe) {
88 }
89 }
90 }
91 return success;
92 }
93
94 /**
95 * Description: 从FTP服务器下载文件
96 *
97 * @param url FTP服务器hostname
98 * @param port FTP服务器端口
99 * @param username FTP登录账号
100 * @param password FTP登录密码
101 * @param remotePath FTP服务器上的相对路径
102 * @param fileName 要下载的文件名
103 * @param localPath 下载后保存到本地的路径
104 * @return
105 */
106 public static boolean downFile(String url, int port, String username, String password, String remotePath,
107 String fileName, String localPath) {
108 boolean success = false;
109 FTPClient ftp = new FTPClient();
110 try {
111 int reply;
112 ftp.connect(url, port);
113 // 如果采用默认端口,可以使用ftp.connect(url)的方式直接连接FTP服务器
114 ftp.login(username, password);// 登录
115 reply = ftp.getReplyCode();
116 if (!FTPReply.isPositiveCompletion(reply)) {
117 ftp.disconnect();
118 return success;
119 }
120 ftp.changeWorkingDirectory(remotePath);// 转移到FTP服务器目录
121 FTPFile[] fs = ftp.listFiles();
122 for (FTPFile ff : fs) {
123 String remotFileName = new String(ff.getName().getBytes("iso-8859-1"), "utf-8");
124 if (remotFileName.equals(fileName)) {
125 File localFile = new File(localPath + "/" + remotFileName);
126 OutputStream is = new FileOutputStream(localFile);
127 ftp.retrieveFile(ff.getName(), is);
128 is.close();
129 }
130 }
131
132 ftp.logout();
133 success = true;
134 } catch (IOException e) {
135 e.printStackTrace();
136 } finally {
137 if (ftp.isConnected()) {
138 try {
139 ftp.disconnect();
140 } catch (IOException ioe) {
141 }
142 }
143 }
144 return success;
145 }
146
147 }
2、解决方法
使用com.jcraft.jsch.JSch提供的SSH解决方法,参考:https://cloud.tencent.com/developer/article/1354612。代码如下:
1 package com.fline.aic.utils;
2
3 import java.io.BufferedReader;
4 import java.io.File;
5 import java.io.FileInputStream;
6 import java.io.FileNotFoundException;
7 import java.io.IOException;
8 import java.io.InputStream;
9 import java.io.InputStreamReader;
10 import java.util.Properties;
11 import java.util.Vector;
12
13 import com.jcraft.jsch.Channel;
14 import com.jcraft.jsch.ChannelExec;
15 import com.jcraft.jsch.ChannelSftp;
16 import com.jcraft.jsch.JSch;
17 import com.jcraft.jsch.JSchException;
18 import com.jcraft.jsch.Session;
19 import com.jcraft.jsch.SftpException;
20
21 /**
22 *
23 * @Description TODO
24 * @author biehl
25 * @Date 2018年10月11日 上午10:20:11
26 *
27 * 说明:exec用于执行命令;sftp用于文件处理
28 */
29 public class SSHRemoteCall {
30
31 // 私有的对象
32 private static SSHRemoteCall sshRemoteCall;
33
34 /**
35 * 私有的构造方法
36 */
37 private SSHRemoteCall() {
38 }
39
40 // 懒汉式,线程不安全,适合单线程
41 public static SSHRemoteCall getInstance() {
42 if (sshRemoteCall == null) {
43 sshRemoteCall = new SSHRemoteCall();
44 }
45 return sshRemoteCall;
46 }
47
48 // 懒汉式,线程安全,适合多线程
49 public static synchronized SSHRemoteCall getInstance2() {
50 if (sshRemoteCall == null) {
51 sshRemoteCall = new SSHRemoteCall();
52 }
53 return sshRemoteCall;
54 }
55
56 private static final int DEFAULT_PORT = 22;// 默认端口号
57 private int port;// 端口号
58
59 private static String ipAddress = "192.168.110.130";// ip地址
60 private static String userName = "root";// 账号
61 private static String password = "hadoop";// 密码
62
63 private Session session;// JSCH session
64 private boolean logined = false;// 是否登陆
65
66 /**
67 * 构造方法,可以直接使用DEFAULT_PORT
68 *
69 * @param ipAddress
70 * @param userName
71 * @param password
72 */
73 public SSHRemoteCall(String ipAddress, String userName, String password) {
74 this(ipAddress, DEFAULT_PORT, userName, password);
75 }
76
77 /**
78 * 构造方法,方便直接传入ipAddress,userName,password进行调用
79 *
80 * @param ipAddress
81 * @param port
82 * @param userName
83 * @param password
84 */
85 public SSHRemoteCall(String ipAddress, int port, String userName, String password) {
86 super();
87 this.ipAddress = ipAddress;
88 this.userName = userName;
89 this.password = password;
90 this.port = port;
91 }
92
93 /**
94 * 远程登陆
95 *
96 * @throws Exception
97 */
98 public void sshRemoteCallLogin(String ipAddress, String userName, String password) throws Exception {
99 // 如果登陆就直接返回
100 if (logined) {
101 return;
102 }
103 // 创建jSch对象
104 JSch jSch = new JSch();
105 try {
106 // 获取到jSch的session, 根据用户名、主机ip、端口号获取一个Session对象
107 session = jSch.getSession(userName, ipAddress, DEFAULT_PORT);
108 // 设置密码
109 session.setPassword(password);
110
111 // 方式一,通过Session建立连接
112 // session.setConfig("StrictHostKeyChecking", "no");
113 // session.connect();
114
115 // 方式二,通过Session建立连接
116 // java.util.Properties;
117 Properties config = new Properties();
118 config.put("StrictHostKeyChecking", "no");
119 session.setConfig(config);// 为Session对象设置properties
120 // session.setTimeout(3000);// 设置超时
121 session.connect();//// 通过Session建立连接
122
123 // 设置登陆状态
124 logined = true;
125 } catch (JSchException e) {
126 // 设置登陆状态为false
127 logined = false;
128 throw new Exception(
129 "主机登录失败, IP = " + ipAddress + ", USERNAME = " + userName + ", Exception:" + e.getMessage());
130 }
131 }
132
133 /**
134 * 关闭连接
135 */
136 public void closeSession() {
137 // 调用session的关闭连接的方法
138 if (session != null) {
139 // 如果session不为空,调用session的关闭连接的方法
140 session.disconnect();
141 }
142
143 }
144
145 /**
146 * 执行相关的命令
147 *
148 * @param command
149 * @throws IOException
150 */
151 public void execCommand(String command) throws IOException {
152 InputStream in = null;// 输入流(读)
153 Channel channel = null;// 定义channel变量
154 try {
155 // 如果命令command不等于null
156 if (command != null) {
157 // 打开channel
158 //说明:exec用于执行命令;sftp用于文件处理
159 channel = session.openChannel("exec");
160 // 设置command
161 ((ChannelExec) channel).setCommand(command);
162 // channel进行连接
163 channel.connect();
164 // 获取到输入流
165 in = channel.getInputStream();
166 // 执行相关的命令
167 String processDataStream = processDataStream(in);
168 // 打印相关的命令
169 System.out.println("1、打印相关返回的命令: " + processDataStream);
170 }
171 } catch (JSchException e) {
172 e.printStackTrace();
173 } catch (IOException e) {
174 e.printStackTrace();
175 } catch (Exception e) {
176 e.printStackTrace();
177 } finally {
178 if (in != null) {
179 in.close();
180 }
181 if (channel != null) {
182 channel.disconnect();
183 }
184 }
185
186 }
187
188 /**
189 * 对将要执行的linux的命令进行遍历
190 *
191 * @param in
192 * @return
193 * @throws Exception
194 */
195 public String processDataStream(InputStream in) throws Exception {
196 StringBuffer sb = new StringBuffer();
197 BufferedReader br = new BufferedReader(new InputStreamReader(in));
198 String result = "";
199 try {
200 while ((result = br.readLine()) != null) {
201 sb.append(result);
202 // System.out.println(sb.toString());
203 }
204 } catch (Exception e) {
205 throw new Exception("获取数据流失败: " + e);
206 } finally {
207 br.close();
208 }
209 return sb.toString();
210 }
211
212 /**
213 * 上传文件 可参考:https://www.cnblogs.com/longyg/archive/2012/06/25/2556576.html
214 *
215 * @param directory
216 * 上传文件的目录
217 * @param uploadFile
218 * 将要上传的文件
219 */
220 public void uploadFile(String directory, String uploadFile) {
221 try {
222 // 打开channelSftp
223 ChannelSftp channelSftp = (ChannelSftp) session.openChannel("sftp");
224 // 远程连接
225 channelSftp.connect();
226 // 创建一个文件名称问uploadFile的文件
227 File file = new File(uploadFile);
228 // 将文件进行上传(sftp协议)
229 // 将本地文件名为src的文件上传到目标服务器,目标文件名为dst,若dst为目录,则目标文件名将与src文件名相同.
230 // 采用默认的传输模式:OVERWRITE
231 channelSftp.put(new FileInputStream(file), directory, ChannelSftp.OVERWRITE);
232 // 切断远程连接
233 channelSftp.exit();
234 System.out.println("2、" + file.getName() + " 文件上传成功.....");
235 } catch (JSchException e) {
236 e.printStackTrace();
237 } catch (SftpException e) {
238 e.printStackTrace();
239 } catch (FileNotFoundException e) {
240 e.printStackTrace();
241 }
242
243 }
244
245 /**
246 * 下载文件 采用默认的传输模式:OVERWRITE
247 *
248 * @param src
249 * linux服务器文件地址
250 * @param dst
251 * 本地存放地址
252 * @throws JSchException
253 * @throws SftpException
254 */
255 public void fileDownload(String src, String dst) throws JSchException, SftpException {
256 // src 是linux服务器文件地址,dst 本地存放地址
257 ChannelSftp channelSftp = (ChannelSftp) session.openChannel("sftp");
258 // 远程连接
259 channelSftp.connect();
260 // 下载文件,多个重载方法
261 channelSftp.get(src, dst);
262 // 切断远程连接,quit()等同于exit(),都是调用disconnect()
263 channelSftp.quit();
264 // channelSftp.disconnect();
265 System.out.println("3、" + src + " ,下载文件成功.....");
266 }
267
268 /**
269 * 删除文件
270 *
271 * @param directory
272 * 要删除文件所在目录
273 * @param deleteFile
274 * 要删除的文件
275 * @param sftp
276 * @throws SftpException
277 * @throws JSchException
278 */
279 public void deleteFile(String directoryFile) throws SftpException, JSchException {
280 // 打开openChannel的sftp
281 ChannelSftp channelSftp = (ChannelSftp) session.openChannel("sftp");
282 // 远程连接
283 channelSftp.connect();
284 // 删除文件
285 channelSftp.rm(directoryFile);
286 // 切断远程连接
287 channelSftp.exit();
288 System.out.println("4、" + directoryFile + " 删除的文件.....");
289 }
290
291 /**
292 * 列出目录下的文件
293 *
294 * @param directory
295 * 要列出的目录
296 * @param sftp
297 * @return
298 * @throws SftpException
299 * @throws JSchException
300 */
301 public Vector listFiles(String directory) throws JSchException, SftpException {
302 ChannelSftp channelSftp = (ChannelSftp) session.openChannel("sftp");
303 // 远程连接
304 channelSftp.connect();
305 // 显示目录信息
306 Vector ls = channelSftp.ls(directory);
307 System.out.println("5、" + ls);
308 // 切断连接
309 channelSftp.exit();
310 return ls;
311 }
312
313 public static void main(String[] args) {
314 // 连接到指定的服务器
315 try {
316 // 1、首先远程连接ssh
317 SSHRemoteCall.getInstance().sshRemoteCallLogin(ipAddress, userName, password);
318 // 打印信息
319 System.out.println("0、连接192.168.110.130,ip地址: " + ipAddress + ",账号: " + userName + ",连接成功.....");
320
321 // 2、执行相关的命令
322 // 查看目录信息
323 // String command = "ls /home/hadoop/package ";
324 // 查看文件信息
325 // String command = "cat /home/hadoop/package/test ";
326 // 查看磁盘空间大小
327 // String command = "df -lh ";
328 // 查看cpu的使用情况
329 // String command = "top -bn 1 -i -c ";
330 // 查看内存的使用情况
331 String command = "free ";
332 SSHRemoteCall.getInstance().execCommand(command);
333
334 // 3、上传文件
335 String directory = "/home/hadoop/package/poi.xlsx";// 目标文件名
336 String uploadFile = "E:\\poi.xlsx";// 本地文件名
337 SSHRemoteCall.getInstance().uploadFile(directory, uploadFile);
338
339 // 4、下载文件
340 // src 是linux服务器文件地址,dst 本地存放地址,采用默认的传输模式:OVERWRITE
341 //test为文件名称哈
342 String src = "/home/hadoop/package/test";
343 String dst = "E:\\";
344 SSHRemoteCall.getInstance().fileDownload(src, dst);
345
346 // 5、刪除文件
347 String deleteDirectoryFile = "/home/hadoop/package/test";
348 SSHRemoteCall.getInstance().deleteFile(deleteDirectoryFile);
349
350 // 6、展示目录下的文件信息
351 String lsDirectory = "/home/hadoop/package";
352 SSHRemoteCall.getInstance().listFiles(lsDirectory);
353
354 // 7、关闭连接
355 SSHRemoteCall.getInstance().closeSession();
356 } catch (Exception e) {
357 // 打印错误信息
358 System.err.println("远程连接失败......");
359 e.printStackTrace();
360 }
361 }
362
363 }