本文共 13479 字,大约阅读时间需要 44 分钟。
1 import java.io.File;
2 import java.io.InputStream;
3 import java.util.ArrayList;
4 import java.util.List;
5 import java.util.Properties;
6 import java.util.Vector;
7 import org.apache.log4j.Logger;
8 import com.jcraft.jsch.ChannelSftp;
9 import com.jcraft.jsch.JSch;
10 import com.jcraft.jsch.JSchException;
11 import com.jcraft.jsch.Session;
12 import com.jcraft.jsch.SftpException;
13 import com.jcraft.jsch.ChannelSftp.LsEntry;
14
15 /**
16 * SFTP(Secure File Transfer Protocol),安全文件传送协议。17 *@version1.0 2014/12/1818 *@authordongliyang19 */
20 public class Sftp {
21
22 /**日志记录器*/
23 private Logger logger = Logger.getLogger(Sftp.class);
24 /**Session*/
25 private Session session = null;
26 /**Channel*/
27 private ChannelSftp channel = null;
28 /**SFTP服务器IP地址*/
29 private String host;
30 /**SFTP服务器端口*/
31 private int port;
32 /**连接超时时间,单位毫秒*/
33 private int timeout;
34
35 /**用户名*/
36 private String username;
37 /**密码*/
38 private String password;
39
40 /**
41 * SFTP 安全文件传送协议42 *@paramhost SFTP服务器IP地址43 *@paramport SFTP服务器端口44 *@paramtimeout 连接超时时间,单位毫秒45 *@paramusername 用户名46 *@parampassword 密码47 */
48 public Sftp(String host,int port,int timeout,String username,String password){
49 this.host = host;
50 this.port = port;
51 this.timeout = timeout;
52 this.username = username;
53 this.password = password;
54 }
55
56 /**
57 * 登陆SFTP服务器58 *@returnboolean59 */
60 public boolean login() {
61
62 try {
63 JSch jsch = new JSch();
64 session = jsch.getSession(username, host, port);
65 if(password != null){
66 session.setPassword(password);
67 }
68 Properties config = new Properties();
69 config.put("StrictHostKeyChecking", "no");
70 session.setConfig(config);
71 session.setTimeout(timeout);
72 session.connect();
73 logger.debug("sftp session connected");
74
75 logger.debug("opening channel");
76 channel = (ChannelSftp)session.openChannel("sftp");
77 channel.connect();
78
79 logger.debug("connected successfully");
80 return true;
81 } catch (JSchException e) {
82 logger.error("sftp login failed",e);
83 return false;
84 }
85 }
86
87 /**
88 * 上传文件89 *
90 * 使用示例,SFTP服务器上的目录结构如下:/testA/testA_B/91 *
当前目录 | 方法 | 参数:绝对路径/相对路径 | 上传后 |
/ | uploadFile("testA","upload.txt",new FileInputStream(new File("up.txt"))) | 相对路径 | /testA/upload.txt |
/ | uploadFile("testA/testA_B","upload.txt",new FileInputStream(new File("up.txt"))) | 相对路径 | /testA/testA_B/upload.txt |
/ | uploadFile("/testA/testA_B","upload.txt",new FileInputStream(new File("up.txt"))) | 绝对路径 | /testA/testA_B/upload.txt |
103 public boolean uploadFile(String pathName,String fileName,InputStream input){
104
105 String currentDir = currentDir();
106 if(!changeDir(pathName)){
107 return false;
108 }
109
110 try {
111 channel.put(input,fileName,ChannelSftp.OVERWRITE);
112 if(!existFile(fileName)){
113 logger.debug("upload failed");
114 return false;
115 }
116 logger.debug("upload successful");
117 return true;
118 } catch (SftpException e) {
119 logger.error("upload failed",e);
120 return false;
121 } finally {
122 changeDir(currentDir);
123 }
124 }
125
126 /**
127 * 上传文件128 *
129 * 使用示例,SFTP服务器上的目录结构如下:/testA/testA_B/130 *
当前目录 | 方法 | 参数:绝对路径/相对路径 | 上传后 |
/ | uploadFile("testA","upload.txt","up.txt") | 相对路径 | /testA/upload.txt |
/ | uploadFile("testA/testA_B","upload.txt","up.txt") | 相对路径 | /testA/testA_B/upload.txt |
/ | uploadFile("/testA/testA_B","upload.txt","up.txt") | 绝对路径 | /testA/testA_B/upload.txt |
142 public boolean uploadFile(String pathName,String fileName,String localFile){
143
144 String currentDir = currentDir();
145 if(!changeDir(pathName)){
146 return false;
147 }
148
149 try {
150 channel.put(localFile,fileName,ChannelSftp.OVERWRITE);
151 if(!existFile(fileName)){
152 logger.debug("upload failed");
153 return false;
154 }
155 logger.debug("upload successful");
156 return true;
157 } catch (SftpException e) {
158 logger.error("upload failed",e);
159 return false;
160 } finally {
161 changeDir(currentDir);
162 }
163 }
164
165 /**
166 * 下载文件167 *
168 * 使用示例,SFTP服务器上的目录结构如下:/testA/testA_B/169 *
当前目录 | 方法 | 参数:绝对路径/相对路径 | 下载后 |
/ | downloadFile("testA","down.txt","D:\\downDir") | 相对路径 | D:\\downDir\\down.txt |
/ | downloadFile("testA/testA_B","down.txt","D:\\downDir") | 相对路径 | D:\\downDir\\down.txt |
/ | downloadFile("/testA/testA_B","down.txt","D:\\downDir") | 绝对路径 | D:\\downDir\\down.txt |
181 public boolean downloadFile(String remotePath,String fileName,String localPath){
182
183 String currentDir = currentDir();
184 if(!changeDir(remotePath)){
185 return false;
186 }
187
188 try {
189 String localFilePath = localPath + File.separator + fileName;
190 channel.get(fileName,localFilePath);
191
192 File localFile = new File(localFilePath);
193 if(!localFile.exists()){
194 logger.debug("download file failed");
195 return false;
196 }
197 logger.debug("download successful");
198 return true;
199 } catch (SftpException e) {
200 logger.error("download file failed",e);
201 return false;
202 } finally {
203 changeDir(currentDir);
204 }
205 }
206
207 /**
208 * 切换工作目录209 *
210 * 使用示例,SFTP服务器上的目录结构如下:/testA/testA_B/211 *
当前目录 | 方法 | 参数(绝对路径/相对路径) | 切换后的目录 |
/ | changeDir("testA") | 相对路径 | /testA/ |
/ | changeDir("testA/testA_B") | 相对路径 | /testA/testA_B/ |
/ | changeDir("/testA") | 绝对路径 | /testA/ |
/testA/testA_B/ | changeDir("/testA") | 绝对路径 | /testA/ |
222 public boolean changeDir(String pathName){
223 if(pathName == null || pathName.trim().equals("")){
224 logger.debug("invalid pathName");
225 return false;
226 }
227
228 try {
229 channel.cd(pathName.replaceAll("\\\\", "/"));
230 logger.debug("directory successfully changed,current dir=" + channel.pwd());
231 return true;
232 } catch (SftpException e) {
233 logger.error("failed to change directory",e);
234 return false;
235 }
236 }
237
238 /**
239 * 切换到上一级目录240 *
241 * 使用示例,SFTP服务器上的目录结构如下:/testA/testA_B/242 *
当前目录 | 方法 | 切换后的目录 |
/testA/ | changeToParentDir() | / |
/testA/testA_B/ | changeToParentDir() | /testA/ |
250 public boolean changeToParentDir(){
251 return changeDir("..");
252 }
253
254 /**
255 * 切换到根目录256 *@returnboolean257 */
258 public boolean changeToHomeDir(){
259 String homeDir = null;
260 try {
261 homeDir = channel.getHome();
262 } catch (SftpException e) {
263 logger.error("can not get home directory",e);
264 return false;
265 }
266 return changeDir(homeDir);
267 }
268
269 /**
270 * 创建目录271 *
272 * 使用示例,SFTP服务器上的目录结构如下:/testA/testA_B/273 *
当前目录 | 方法 | 参数(绝对路径/相对路径) | 创建成功后的目录 |
/testA/testA_B/ | makeDir("testA_B_C") | 相对路径 | /testA/testA_B/testA_B_C/ |
/ | makeDir("/testA/testA_B/testA_B_D") | 绝对路径 | /testA/testA_B/testA_B_D/ |
285 public boolean makeDir(String dirName){
286 try {
287 channel.mkdir(dirName);
288 logger.debug("directory successfully created,dir=" + dirName);
289 return true;
290 } catch (SftpException e) {
291 logger.error("failed to create directory", e);
292 return false;
293 }
294 }
295
296 /**
297 * 删除文件夹298 *@paramdirName299 *@returnboolean300 */
301 @SuppressWarnings("unchecked")
302 public boolean delDir(String dirName){
303 if(!changeDir(dirName)){
304 return false;
305 }
306
307 Vector list = null;
308 try {
309 list = channel.ls(channel.pwd());
310 } catch (SftpException e) {
311 logger.error("can not list directory",e);
312 return false;
313 }
314
315 for(LsEntry entry : list){
316 String fileName = entry.getFilename();
317 if(!fileName.equals(".") && !fileName.equals("..")){
318 if(entry.getAttrs().isDir()){
319 delDir(fileName);
320 } else {
321 delFile(fileName);
322 }
323 }
324 }
325
326 if(!changeToParentDir()){
327 return false;
328 }
329
330 try {
331 channel.rmdir(dirName);
332 logger.debug("directory " + dirName + " successfully deleted");
333 return true;
334 } catch (SftpException e) {
335 logger.error("failed to delete directory " + dirName,e);
336 return false;
337 }
338 }
339
340 /**
341 * 删除文件342 *@paramfileName 文件名343 *@returnboolean344 */
345 public boolean delFile(String fileName){
346 if(fileName == null || fileName.trim().equals("")){
347 logger.debug("invalid filename");
348 return false;
349 }
350
351 try {
352 channel.rm(fileName);
353 logger.debug("file " + fileName + " successfully deleted");
354 return true;
355 } catch (SftpException e) {
356 logger.error("failed to delete file " + fileName,e);
357 return false;
358 }
359 }
360
361 /**
362 * 当前目录下文件及文件夹名称列表363 *@returnString[]364 */
365 public String[] ls(){
366 return list(Filter.ALL);
367 }
368
369 /**
370 * 指定目录下文件及文件夹名称列表371 *@returnString[]372 */
373 public String[] ls(String pathName){
374 String currentDir = currentDir();
375 if(!changeDir(pathName)){
376 return new String[0];
377 };
378 String[] result = list(Filter.ALL);
379 if(!changeDir(currentDir)){
380 return new String[0];
381 }
382 return result;
383 }
384
385 /**
386 * 当前目录下文件名称列表387 *@returnString[]388 */
389 public String[] lsFiles(){
390 return list(Filter.FILE);
391 }
392
393 /**
394 * 指定目录下文件名称列表395 *@returnString[]396 */
397 public String[] lsFiles(String pathName){
398 String currentDir = currentDir();
399 if(!changeDir(pathName)){
400 return new String[0];
401 };
402 String[] result = list(Filter.FILE);
403 if(!changeDir(currentDir)){
404 return new String[0];
405 }
406 return result;
407 }
408
409 /**
410 * 当前目录下文件夹名称列表411 *@returnString[]412 */
413 public String[] lsDirs(){
414 return list(Filter.DIR);
415 }
416
417 /**
418 * 指定目录下文件夹名称列表419 *@returnString[]420 */
421 public String[] lsDirs(String pathName){
422 String currentDir = currentDir();
423 if(!changeDir(pathName)){
424 return new String[0];
425 };
426 String[] result = list(Filter.DIR);
427 if(!changeDir(currentDir)){
428 return new String[0];
429 }
430 return result;
431 }
432
433 /**
434 * 当前目录是否存在文件或文件夹435 *@paramname 名称436 *@returnboolean437 */
438 public boolean exist(String name){
439 return exist(ls(), name);
440 }
441
442 /**
443 * 指定目录下,是否存在文件或文件夹444 *@parampath 目录445 *@paramname 名称446 *@returnboolean447 */
448 public boolean exist(String path,String name){
449 return exist(ls(path),name);
450 }
451
452 /**
453 * 当前目录是否存在文件454 *@paramname 文件名455 *@returnboolean456 */
457 public boolean existFile(String name){
458 return exist(lsFiles(),name);
459 }
460
461 /**
462 * 指定目录下,是否存在文件463 *@parampath 目录464 *@paramname 文件名465 *@returnboolean466 */
467 public boolean existFile(String path,String name){
468 return exist(lsFiles(path), name);
469 }
470
471 /**
472 * 当前目录是否存在文件夹473 *@paramname 文件夹名称474 *@returnboolean475 */
476 public boolean existDir(String name){
477 return exist(lsDirs(), name);
478 }
479
480 /**
481 * 指定目录下,是否存在文件夹482 *@parampath 目录483 *@paramname 文家夹名称484 *@returnboolean485 */
486 public boolean existDir(String path,String name){
487 return exist(lsDirs(path), name);
488 }
489
490 /**
491 * 当前工作目录492 *@returnString493 */
494 public String currentDir(){
495 try {
496 return channel.pwd();
497 } catch (SftpException e) {
498 logger.error("failed to get current dir",e);
499 return homeDir();
500 }
501 }
502
503 /**
504 * 登出505 */
506 public void logout(){
507 if(channel != null){
508 channel.quit();
509 channel.disconnect();
510 }
511 if(session != null){
512 session.disconnect();
513 }
514 logger.debug("logout successfully");
515 }
516
517
518 //------private method ------
519
520 /**枚举,用于过滤文件和文件夹*/
521 private enum Filter {/**文件及文件夹*/ ALL ,/**文件*/ FILE ,/**文件夹*/ DIR };
522
523 /**
524 * 列出当前目录下的文件及文件夹525 *@paramfilter 过滤参数526 *@returnString[]527 */
528 @SuppressWarnings("unchecked")
529 private String[] list(Filter filter){
530 Vector list = null;
531 try {
532 //ls方法会返回两个特殊的目录,当前目录(.)和父目录(..)
533 list = channel.ls(channel.pwd());
534 } catch (SftpException e) {
535 logger.error("can not list directory",e);
536 return new String[0];
537 }
538
539 List resultList = new ArrayList();
540 for(LsEntry entry : list){
541 if(filter(entry, filter)){
542 resultList.add(entry.getFilename());
543 }
544 }
545 return resultList.toArray(new String[0]);
546 }
547
548 /**
549 * 判断是否是否过滤条件550 *@paramentry LsEntry551 *@paramf 过滤参数552 *@returnboolean553 */
554 private boolean filter(LsEntry entry,Filter f){
555 if(f.equals(Filter.ALL)){
556 return !entry.getFilename().equals(".") && !entry.getFilename().equals("..");
557 } else if(f.equals(Filter.FILE)){
558 return !entry.getFilename().equals(".") && !entry.getFilename().equals("..") && !entry.getAttrs().isDir();
559 } else if(f.equals(Filter.DIR)){
560 return !entry.getFilename().equals(".") && !entry.getFilename().equals("..") && entry.getAttrs().isDir();
561 }
562 return false;
563 }
564
565 /**
566 * 根目录567 *@returnString568 */
569 private String homeDir(){
570 try {
571 return channel.getHome();
572 } catch (SftpException e) {
573 return "/";
574 }
575 }
576
577 /**
578 * 判断字符串是否存在于数组中579 *@paramstrArr 字符串数组580 *@paramstr 字符串581 *@returnboolean582 */
583 private boolean exist(String[] strArr,String str){
584 if(strArr == null || strArr.length == 0){
585 return false;
586 }
587 if(str == null || str.trim().equals("")){
588 return false;
589 }
590 for(String s : strArr){
591 if(s.equalsIgnoreCase(str)){
592 return true;
593 }
594 }
595 return false;
596 }
597
598
599 //------private method ------
600 }
转载地址:https://blog.csdn.net/weixin_33137081/article/details/114279964 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!