zoukankan      html  css  js  c++  java
  • 文件系统之-JAVA Sftp远程操作:

    转载:http://blog.csdn.net/lee272616/article/details/52789018

    java远程操作文件服务器(linux),使用sftp协议
    版本会持续更新,
    当前版本:0.31
    版本更新时间:2016-10-13
    版本修正说明:
    1.修正连接关闭,将关闭的方法改成私有,不允许使用者自行关闭(否则会导致连接池获取错误)

    2.优化删除文件及文件夹,先判断文件或文件夹是否存在,然后再删除

    前言:

    sftp是Secure File Transfer Protocol的缩写,安全文件传送协议。可以为传输文件提供一种安全的加密方法。sftp 与 ftp 有着几乎一样的语法和功能。SFTP 为 SSH的一部分,是一种传输档案至 Blogger 伺服器的安全方式。其实在SSH软件包中,已经包含了一个叫作SFTP(Secure File Transfer Protocol)的安全文件传输子系统,SFTP本身没有单独的守护进程,它必须使用sshd守护进程(端口号默认是22)来完成相应的连接操作,所以从某种意义上来说,SFTP并不像一个服务器程序,而更像是一个客户端程序。SFTP同样是使用加密传输认证信息和传输的数据,所以,使用SFTP是非常安全的。但是,由于这种传输方式使用了加密/解密技术,所以传输效率比普通的FTP要低得多,如果您对网络安全性要求更高时,可以使用SFTP代替FTP。

    本工具基于对JSch - Java Secure Channel进行的封装,linux服务器不用安装任何插件和软件

    使用指南:

    首先是jar包

    [html] view plain copy
     
    1. <dependency>  
    2.   <groupId>com.jcraft</groupId>  
    3.   <artifactId>jsch</artifactId>  
    4.   <version>0.1.42</version>  
    5. </dependency>  

    Sftp协议工具类-v0.1

    [java] view plain copy
     
    1. package com.noryar.filesystem.utils;  
    2.   
    3. import java.io.ByteArrayOutputStream;  
    4. import java.io.File;  
    5. import java.io.FileOutputStream;  
    6. import java.util.ArrayList;  
    7. import java.util.List;  
    8. import java.util.Properties;  
    9. import java.util.Vector;  
    10.   
    11. import org.apache.commons.lang.StringUtils;  
    12.   
    13. import com.jcraft.jsch.Channel;  
    14. import com.jcraft.jsch.ChannelSftp;  
    15. import com.jcraft.jsch.JSch;  
    16. import com.jcraft.jsch.JSchException;  
    17. import com.jcraft.jsch.Session;  
    18. import com.jcraft.jsch.SftpException;  
    19.   
    20. /** 
    21.  * 文件工具类. 
    22.  * @author Leon Lee 
    23.  */  
    24. public class SftpUtil {  
    25.   
    26.     /** 
    27.      * 文件路径前缀. /ddit-remote 
    28.      */  
    29.     private static final String PRE_FIX = "/test-noryar";  
    30.   
    31.     /** 
    32.      * 获取sftp协议连接. 
    33.      * @param host 主机名 
    34.      * @param port 端口 
    35.      * @param username 用户名 
    36.      * @param password 密码 
    37.      * @return 连接对象 
    38.      * @throws JSchException 异常 
    39.      */  
    40.     public static ChannelSftp getSftpConnect(final String host, final int port, final String username,  
    41.             final String password) throws JSchException {  
    42.         ChannelSftp sftp = null;  
    43.         JSch jsch = new JSch();  
    44.         jsch.getSession(username, host, port);  
    45.         Session sshSession = jsch.getSession(username, host, port);  
    46.         sshSession.setPassword(password);  
    47.         Properties sshConfig = new Properties();  
    48.         sshConfig.put("StrictHostKeyChecking", "no");  
    49.         sshSession.setConfig(sshConfig);  
    50.         sshSession.connect();  
    51.         Channel channel = sshSession.openChannel("sftp");  
    52.         channel.connect();  
    53.         sftp = (ChannelSftp) channel;  
    54.         return sftp;  
    55.     }  
    56.   
    57.     /** 
    58.      * 下载文件-sftp协议. 
    59.      * @param downloadFile 下载的文件 
    60.      * @param saveFile 存在本地的路径 
    61.      * @param sftp sftp连接 
    62.      * @return 文件 
    63.      * @throws Exception 异常 
    64.      */  
    65.     public static File download(final String downloadFile, final String saveFile, final ChannelSftp sftp)  
    66.             throws Exception {  
    67.         FileOutputStream os = null;  
    68.         File file = new File(saveFile);  
    69.         try {  
    70.             if (!file.exists()) {  
    71.                 File parentFile = file.getParentFile();  
    72.                 if (!parentFile.exists()) {  
    73.                     parentFile.mkdirs();  
    74.                 }  
    75.                 file.createNewFile();  
    76.             }  
    77.             os = new FileOutputStream(file);  
    78.             List<String> list = formatPath(downloadFile);  
    79.             sftp.get(list.get(0) + list.get(1), os);  
    80.         } catch (Exception e) {  
    81.             exit(sftp);  
    82.             throw e;  
    83.         } finally {  
    84.             os.close();  
    85.         }  
    86.         return file;  
    87.     }  
    88.   
    89.     /** 
    90.      * 下载文件-sftp协议. 
    91.      * @param downloadFile 下载的文件 
    92.      * @param saveFile 存在本地的路径 
    93.      * @param sftp sftp连接 
    94.      * @return 文件 byte[] 
    95.      * @throws Exception 异常 
    96.      */  
    97.     public static byte[] downloadAsByte(final String downloadFile, final ChannelSftp sftp) throws Exception {  
    98.         ByteArrayOutputStream os = new ByteArrayOutputStream();  
    99.         try {  
    100.             List<String> list = formatPath(downloadFile);  
    101.             sftp.get(list.get(0) + list.get(1), os);  
    102.         } catch (Exception e) {  
    103.             exit(sftp);  
    104.             throw e;  
    105.         } finally {  
    106.             os.close();  
    107.         }  
    108.         return os.toByteArray();  
    109.     }  
    110.   
    111.     /** 
    112.      * 删除文件-sftp协议. 
    113.      * @param deleteFile 要删除的文件 
    114.      * @param sftp sftp连接 
    115.      * @throws Exception 异常 
    116.      */  
    117.     public static void rmFile(final String deleteFile, final ChannelSftp sftp) throws Exception {  
    118.         try {  
    119.             sftp.rm(deleteFile);  
    120.         } catch (Exception e) {  
    121.             exit(sftp);  
    122.             throw e;  
    123.         }  
    124.     }  
    125.   
    126.     /** 
    127.      * 删除文件夹-sftp协议. 
    128.      * @param deleteFile 文件夹路径 
    129.      * @param sftp sftp连接 
    130.      * @throws Exception 异常 
    131.      */  
    132.     public static void rmDir(final String pathString, final ChannelSftp sftp) throws Exception {  
    133.         try {  
    134.             sftp.rmdir(pathString);  
    135.         } catch (Exception e) {  
    136.             exit(sftp);  
    137.             throw e;  
    138.         }  
    139.     }  
    140.   
    141.     /** 
    142.      * 上传文件-sftp协议. 
    143.      * @param srcFile 源文件 
    144.      * @param dir 保存路径 
    145.      * @param fileName 保存文件名 
    146.      * @param sftp sftp连接 
    147.      * @throws Exception 异常 
    148.      */  
    149.     private static void uploadFile(final String srcFile, final String dir, final String fileName, final ChannelSftp sftp)  
    150.             throws Exception {  
    151.         mkdir(dir, sftp);  
    152.         sftp.cd(dir);  
    153.         sftp.put(srcFile, fileName);  
    154.     }  
    155.   
    156.     /** 
    157.      * 上传文件-sftp协议. 
    158.      * @param srcFile 源文件路径,/xxx/xxx.zip 或 x:/xxx/xxx.zip; 
    159.      * @param sftp sftp连接 
    160.      * @throws Exception 异常 
    161.      */  
    162.     public static void uploadFile(final String srcFile, final ChannelSftp sftp) throws Exception {  
    163.         try {  
    164.             File file = new File(srcFile);  
    165.             if (file.exists()) {  
    166.                 List<String> list = formatPath(srcFile);  
    167.                 uploadFile(srcFile, list.get(0), list.get(1), sftp);  
    168.             }  
    169.         } catch (Exception e) {  
    170.             exit(sftp);  
    171.             throw e;  
    172.         }  
    173.     }  
    174.   
    175.     /** 
    176.      * 根据路径创建文件夹. 
    177.      * @param dir 路径 必须是 /xxx/xxx/xxx/ 不能就单独一个/ 
    178.      * @param sftp sftp连接 
    179.      * @throws Exception 异常 
    180.      */  
    181.     public static boolean mkdir(final String dir, final ChannelSftp sftp) throws Exception {  
    182.         try {  
    183.             if (StringUtils.isBlank(dir))  
    184.                 return false;  
    185.             String md = dir.replaceAll("\\", "/");  
    186.             if (md.indexOf("/") != 0 || md.length() == 1)  
    187.                 return false;  
    188.             return mkdirs(md, sftp);  
    189.         } catch (Exception e) {  
    190.             exit(sftp);  
    191.             throw e;  
    192.         }  
    193.     }  
    194.   
    195.     /** 
    196.      * 递归创建文件夹. 
    197.      * @param dir 路径 
    198.      * @param sftp sftp连接 
    199.      * @return 是否创建成功 
    200.      * @throws SftpException 异常 
    201.      */  
    202.     private static boolean mkdirs(final String dir, final ChannelSftp sftp) throws SftpException {  
    203.         String dirs = dir.substring(1, dir.length() - 1);  
    204.         String[] dirArr = dirs.split("/");  
    205.         String base = "";  
    206.         for (String d : dirArr) {  
    207.             base += "/" + d;  
    208.             if (dirExist(base + "/", sftp)) {  
    209.                 continue;  
    210.             } else {  
    211.                 sftp.mkdir(base + "/");  
    212.             }  
    213.         }  
    214.         return true;  
    215.     }  
    216.   
    217.     /** 
    218.      * 判断文件夹是否存在. 
    219.      * @param dir 文件夹路径, /xxx/xxx/ 
    220.      * @param sftp sftp协议 
    221.      * @return 是否存在 
    222.      */  
    223.     public static boolean dirExist(final String dir, final ChannelSftp sftp) {  
    224.         try {  
    225.             Vector<?> vector = sftp.ls(dir);  
    226.             if (null == vector)  
    227.                 return false;  
    228.             else  
    229.                 return true;  
    230.         } catch (SftpException e) {  
    231.             return false;  
    232.         }  
    233.     }  
    234.   
    235.     /** 
    236.      * 格式化路径. 
    237.      * @param srcPath 原路径. /xxx/xxx/xxx.yyy 或 X:/xxx/xxx/xxx.yy 
    238.      * @return list, 第一个是路径(/xxx/xxx/),第二个是文件名(xxx.yy) 
    239.      */  
    240.     public static List<String> formatPath(final String srcPath) {  
    241.         List<String> list = new ArrayList<String>(2);  
    242.         String dir = "";  
    243.         String fileName = "";  
    244.         String repSrc = srcPath.replaceAll("\\", "/");  
    245.         int firstP = repSrc.indexOf("/");  
    246.         int lastP = repSrc.lastIndexOf("/");  
    247.         fileName = repSrc.substring(lastP + 1);  
    248.         dir = repSrc.substring(firstP, lastP);  
    249.         dir = PRE_FIX + (dir.length() == 1 ? dir : (dir + "/"));  
    250.         list.add(dir);  
    251.         list.add(fileName);  
    252.         return list;  
    253.     }  
    254.   
    255.     /** 
    256.      * 关闭协议-sftp协议. 
    257.      * @param sftp sftp连接 
    258.      */  
    259.     public static void exit(final ChannelSftp sftp) {  
    260.         sftp.exit();  
    261.     }  
    262.   
    263.     public static void main(String[] args) throws Exception {  
    264.         ChannelSftp sftp = getSftpConnect("192.168.0.35", 22, "root", "root");  
    265.         String pathString = "C:\test\aaa\Foxmail7.zip";  
    266.         File file = new File(pathString);  
    267.         System.out.println("上传文件开始...");  
    268.         uploadFile(pathString, sftp);  
    269.         System.out.println("上传成功,开始删除本地文件...");  
    270.         file.delete();  
    271.         System.out.println("删除完成,开始校验本地文件...");  
    272.         if (!file.exists()) {  
    273.             System.out.println("文件不存在,开始从远程服务器获取...");  
    274.             download(pathString, pathString, sftp);  
    275.             System.out.println("下载完成");  
    276.         } else {  
    277.             System.out.println("在本地找到文件");  
    278.         }  
    279.         exit(sftp);  
    280.         System.exit(0);  
    281.     }  
    282. }  

    v0.2-新增sftp连接池

    由于创建sftp连接的花销比较大,因此考虑相同主机的连接存放在连接池中,下次获取sftp连接的时候直接去连接池获取
    以下代码替换v0.1版的getSftpConnect()方法,并加上成员变量即可
    [java] view plain copy
     
    1. /** 
    2.  * sftp连接池. 
    3.  */  
    4. private static final Map<String, Channel> SFTP_CHANNEL_POOL = new HashMap<String, Channel>();  
    5.   
    6. /** 
    7.  * 获取sftp协议连接. 
    8.  * @param host 主机名 
    9.  * @param port 端口 
    10.  * @param username 用户名 
    11.  * @param password 密码 
    12.  * @return 连接对象 
    13.  * @throws JSchException 异常 
    14.  */  
    15. public static ChannelSftp getSftpConnect(final String host, final int port, final String username,  
    16.         final String password) throws JSchException {  
    17.     Session sshSession = null;  
    18.     Channel channel = null;  
    19.     ChannelSftp sftp = null;  
    20.     String key = host + "," + port + "," + username + "," + password;  
    21.     if (null == SFTP_CHANNEL_POOL.get(key)) {  
    22.         JSch jsch = new JSch();  
    23.         jsch.getSession(username, host, port);  
    24.         sshSession = jsch.getSession(username, host, port);  
    25.         sshSession.setPassword(password);  
    26.         Properties sshConfig = new Properties();  
    27.         sshConfig.put("StrictHostKeyChecking", "no");  
    28.         sshSession.setConfig(sshConfig);  
    29.         sshSession.connect();  
    30.         channel = sshSession.openChannel("sftp");  
    31.         channel.connect();  
    32.         SFTP_CHANNEL_POOL.put(key, channel);  
    33.     } else {  
    34.         channel = SFTP_CHANNEL_POOL.get(key);  
    35.         sshSession = channel.getSession();  
    36.         if (!sshSession.isConnected())  
    37.             sshSession.connect();  
    38.         if (!channel.isConnected())  
    39.             channel.connect();  
    40.     }  
    41.     sftp = (ChannelSftp) channel;  
    42.     return sftp;  
    43. }  

    v0.3-修改了一些bug,新增递归删除文件夹功能

    [java] view plain copy
     
    1. package com.noryar.filesystem.utils;  
    2.   
    3. import java.io.ByteArrayOutputStream;  
    4. import java.io.File;  
    5. import java.io.FileOutputStream;  
    6. import java.util.ArrayList;  
    7. import java.util.HashMap;  
    8. import java.util.List;  
    9. import java.util.Map;  
    10. import java.util.Properties;  
    11. import java.util.Vector;  
    12.   
    13. import org.apache.commons.lang.StringUtils;  
    14.   
    15. import com.jcraft.jsch.Channel;  
    16. import com.jcraft.jsch.ChannelSftp;  
    17. import com.jcraft.jsch.ChannelSftp.LsEntry;  
    18. import com.jcraft.jsch.JSch;  
    19. import com.jcraft.jsch.JSchException;  
    20. import com.jcraft.jsch.Session;  
    21. import com.jcraft.jsch.SftpException;  
    22.   
    23. /** 
    24.  * 文件工具类.<br> 
    25.  * 1.所有的文件路径必须以'/'开头和结尾,否则路径最后一部分会被当做是文件名<br> 
    26.  * 2.方法出现异常的时候,会关闭sftp连接(但是不会关闭session和channel),异常会抛出 
    27.  * @author Leon Lee 
    28.  */  
    29. public class SftpUtil {  
    30.   
    31.     /** 
    32.      * 文件路径前缀. /ddit-remote 
    33.      */  
    34.     private static final String PRE_FIX = "/test-noryar";  
    35.   
    36.     /** 
    37.      * sftp连接池. 
    38.      */  
    39.     private static final Map<String, Channel> SFTP_CHANNEL_POOL = new HashMap<String, Channel>();  
    40.   
    41.     /** 
    42.      * 获取sftp协议连接. 
    43.      * @param host 主机名 
    44.      * @param port 端口 
    45.      * @param username 用户名 
    46.      * @param password 密码 
    47.      * @return 连接对象 
    48.      * @throws JSchException 异常 
    49.      */  
    50.     public static ChannelSftp getSftpConnect(final String host, final int port, final String username,  
    51.             final String password) throws JSchException {  
    52.         Session sshSession = null;  
    53.         Channel channel = null;  
    54.         ChannelSftp sftp = null;  
    55.         String key = host + "," + port + "," + username + "," + password;  
    56.         if (null == SFTP_CHANNEL_POOL.get(key)) {  
    57.             JSch jsch = new JSch();  
    58.             jsch.getSession(username, host, port);  
    59.             sshSession = jsch.getSession(username, host, port);  
    60.             sshSession.setPassword(password);  
    61.             Properties sshConfig = new Properties();  
    62.             sshConfig.put("StrictHostKeyChecking", "no");  
    63.             sshSession.setConfig(sshConfig);  
    64.             sshSession.connect();  
    65.             channel = sshSession.openChannel("sftp");  
    66.             channel.connect();  
    67.             SFTP_CHANNEL_POOL.put(key, channel);  
    68.         } else {  
    69.             channel = SFTP_CHANNEL_POOL.get(key);  
    70.             sshSession = channel.getSession();  
    71.             if (!sshSession.isConnected())  
    72.                 sshSession.connect();  
    73.             if (!channel.isConnected())  
    74.                 channel.connect();  
    75.         }  
    76.         sftp = (ChannelSftp) channel;  
    77.         return sftp;  
    78.     }  
    79.   
    80.     /** 
    81.      * 下载文件-sftp协议. 
    82.      * @param downloadFile 下载的文件 
    83.      * @param saveFile 存在本地的路径 
    84.      * @param sftp sftp连接 
    85.      * @return 文件 
    86.      * @throws Exception 异常 
    87.      */  
    88.     public static File download(final String downloadFile, final String saveFile, final ChannelSftp sftp)  
    89.             throws Exception {  
    90.         FileOutputStream os = null;  
    91.         File file = new File(saveFile);  
    92.         try {  
    93.             if (!file.exists()) {  
    94.                 File parentFile = file.getParentFile();  
    95.                 if (!parentFile.exists()) {  
    96.                     parentFile.mkdirs();  
    97.                 }  
    98.                 file.createNewFile();  
    99.             }  
    100.             os = new FileOutputStream(file);  
    101.             List<String> list = formatPath(downloadFile);  
    102.             sftp.get(list.get(0) + list.get(1), os);  
    103.         } catch (Exception e) {  
    104.             exit(sftp);  
    105.             e.getMessage();  
    106.             throw e;  
    107.         } finally {  
    108.             os.close();  
    109.         }  
    110.         return file;  
    111.     }  
    112.   
    113.     /** 
    114.      * 下载文件-sftp协议. 
    115.      * @param downloadFile 下载的文件 
    116.      * @param saveFile 存在本地的路径 
    117.      * @param sftp sftp连接 
    118.      * @return 文件 byte[] 
    119.      * @throws Exception 异常 
    120.      */  
    121.     public static byte[] downloadAsByte(final String downloadFile, final ChannelSftp sftp) throws Exception {  
    122.         ByteArrayOutputStream os = new ByteArrayOutputStream();  
    123.         try {  
    124.             List<String> list = formatPath(downloadFile);  
    125.             sftp.get(list.get(0) + list.get(1), os);  
    126.         } catch (Exception e) {  
    127.             exit(sftp);  
    128.             throw e;  
    129.         } finally {  
    130.             os.close();  
    131.         }  
    132.         return os.toByteArray();  
    133.     }  
    134.   
    135.     /** 
    136.      * 删除文件-sftp协议. 
    137.      * @param pathString 要删除的文件 
    138.      * @param sftp sftp连接 
    139.      * @throws Exception 异常 
    140.      */  
    141.     public static void rmFile(final String pathString, final ChannelSftp sftp) throws Exception {  
    142.         try {  
    143.             List<String> list = formatPath(pathString);  
    144.             sftp.rm(list.get(0) + list.get(1));  
    145.         } catch (Exception e) {  
    146.             exit(sftp);  
    147.             throw e;  
    148.         }  
    149.     }  
    150.   
    151.     /** 
    152.      * 删除文件夹-sftp协议.如果文件夹有内容,则会抛出异常. 
    153.      * @param pathString 文件夹路径 
    154.      * @param sftp sftp连接 
    155.      * @param resursion 递归删除 
    156.      * @throws Exception 异常 
    157.      */  
    158.     public static void rmDir(final String pathString, final ChannelSftp sftp, final boolean recursion) throws Exception {  
    159.         try {  
    160.             String fp = formatPath(pathString).get(0);  
    161.             if (recursion)  
    162.                 exeRmRec(fp, sftp);  
    163.             else  
    164.                 sftp.rmdir(fp);  
    165.         } catch (Exception e) {  
    166.             exit(sftp);  
    167.             throw e;  
    168.         }  
    169.     }  
    170.   
    171.     /** 
    172.      * 递归删除执行. 
    173.      * @param pathString 文件路径 
    174.      * @param sftp sftp连接 
    175.      * @throws SftpException 
    176.      */  
    177.     private static void exeRmRec(final String pathString, final ChannelSftp sftp) throws SftpException {  
    178.         @SuppressWarnings("unchecked")  
    179.         Vector<LsEntry> vector = sftp.ls(pathString);  
    180.         if (vector.size() == 1) { // 文件,直接删除  
    181.             sftp.rm(pathString);  
    182.         } else if (vector.size() == 2) { // 空文件夹,直接删除  
    183.             sftp.rmdir(pathString);  
    184.         } else {  
    185.             String fileName = "";  
    186.             // 删除文件夹下所有文件  
    187.             for (LsEntry en : vector) {  
    188.                 fileName = en.getFilename();  
    189.                 if (".".equals(fileName) || "..".equals(fileName)) {  
    190.                     continue;  
    191.                 } else {  
    192.                     exeRmRec(pathString + "/" + fileName, sftp);  
    193.                 }  
    194.             }  
    195.             // 删除文件夹  
    196.             sftp.rmdir(pathString);  
    197.         }  
    198.     }  
    199.   
    200.     /** 
    201.      * 上传文件-sftp协议. 
    202.      * @param srcFile 源文件 
    203.      * @param dir 保存路径 
    204.      * @param fileName 保存文件名 
    205.      * @param sftp sftp连接 
    206.      * @throws Exception 异常 
    207.      */  
    208.     private static void uploadFile(final String srcFile, final String dir, final String fileName, final ChannelSftp sftp)  
    209.             throws Exception {  
    210.         mkdir(dir, sftp);  
    211.         sftp.cd(dir);  
    212.         sftp.put(srcFile, fileName);  
    213.     }  
    214.   
    215.     /** 
    216.      * 上传文件-sftp协议. 
    217.      * @param srcFile 源文件路径,/xxx/xx.yy 或 x:/xxx/xxx.yy 
    218.      * @param sftp sftp连接 
    219.      * @return 上传成功与否 
    220.      * @throws Exception 异常 
    221.      */  
    222.     public static boolean uploadFile(final String srcFile, final ChannelSftp sftp) throws Exception {  
    223.         try {  
    224.             File file = new File(srcFile);  
    225.             if (file.exists()) {  
    226.                 List<String> list = formatPath(srcFile);  
    227.                 uploadFile(srcFile, list.get(0), list.get(1), sftp);  
    228.                 return true;  
    229.             }  
    230.             return false;  
    231.         } catch (Exception e) {  
    232.             exit(sftp);  
    233.             throw e;  
    234.         }  
    235.     }  
    236.   
    237.     /** 
    238.      * 根据路径创建文件夹. 
    239.      * @param dir 路径 必须是 /xxx/xxx/ 不能就单独一个/ 
    240.      * @param sftp sftp连接 
    241.      * @throws Exception 异常 
    242.      */  
    243.     public static boolean mkdir(final String dir, final ChannelSftp sftp) throws Exception {  
    244.         try {  
    245.             if (StringUtils.isBlank(dir))  
    246.                 return false;  
    247.             String md = dir.replaceAll("\\", "/");  
    248.             if (md.indexOf("/") != 0 || md.length() == 1)  
    249.                 return false;  
    250.             return mkdirs(md, sftp);  
    251.         } catch (Exception e) {  
    252.             exit(sftp);  
    253.             throw e;  
    254.         }  
    255.     }  
    256.   
    257.     /** 
    258.      * 递归创建文件夹. 
    259.      * @param dir 路径 
    260.      * @param sftp sftp连接 
    261.      * @return 是否创建成功 
    262.      * @throws SftpException 异常 
    263.      */  
    264.     private static boolean mkdirs(final String dir, final ChannelSftp sftp) throws SftpException {  
    265.         String dirs = dir.substring(1, dir.length() - 1);  
    266.         String[] dirArr = dirs.split("/");  
    267.         String base = "";  
    268.         for (String d : dirArr) {  
    269.             base += "/" + d;  
    270.             if (dirExist(base + "/", sftp)) {  
    271.                 continue;  
    272.             } else {  
    273.                 sftp.mkdir(base + "/");  
    274.             }  
    275.         }  
    276.         return true;  
    277.     }  
    278.   
    279.     /** 
    280.      * 判断文件夹是否存在. 
    281.      * @param dir 文件夹路径, /xxx/xxx/ 
    282.      * @param sftp sftp协议 
    283.      * @return 是否存在 
    284.      */  
    285.     private static boolean dirExist(final String dir, final ChannelSftp sftp) {  
    286.         try {  
    287.             Vector<?> vector = sftp.ls(dir);  
    288.             if (null == vector)  
    289.                 return false;  
    290.             else  
    291.                 return true;  
    292.         } catch (SftpException e) {  
    293.             return false;  
    294.         }  
    295.     }  
    296.   
    297.     /** 
    298.      * 格式化路径. 
    299.      * @param srcPath 原路径. /xxx/xxx/xxx.yyy 或 X:/xxx/xxx/xxx.yy 
    300.      * @return list, 第一个是路径(/xxx/xxx/),第二个是文件名(xxx.yy) 
    301.      */  
    302.     public static List<String> formatPath(final String srcPath) {  
    303.         List<String> list = new ArrayList<String>(2);  
    304.         String repSrc = srcPath.replaceAll("\\", "/");  
    305.         int firstP = repSrc.indexOf("/");  
    306.         int lastP = repSrc.lastIndexOf("/");  
    307.         String fileName = lastP + 1 == repSrc.length() ? "" : repSrc.substring(lastP + 1);  
    308.         String dir = firstP == -1 ? "" : repSrc.substring(firstP, lastP);  
    309.         dir = PRE_FIX + (dir.length() == 1 ? dir : (dir + "/"));  
    310.         list.add(dir);  
    311.         list.add(fileName);  
    312.         return list;  
    313.     }  
    314.   
    315.     /** 
    316.      * 关闭协议-sftp协议. 
    317.      * @param sftp sftp连接 
    318.      */  
    319.     public static void exit(final ChannelSftp sftp) {  
    320.         sftp.exit();  
    321.     }  
    322.   
    323.     public static void main(String[] args) throws Exception {  
    324.         ChannelSftp sftp = getSftpConnect("192.168.0.35", 22, "root", "root");  
    325.         // String pathString = "C:\test\ccc\Foxmail7.zip";  
    326.         // File file = new File(pathString);  
    327.         // System.out.println("上传文件开始...");  
    328.         // uploadFile(pathString, sftp);  
    329.         // System.out.println("上传成功,开始删除本地文件...");  
    330.         // file.delete();  
    331.         // System.out.println("删除完成,开始校验本地文件...");  
    332.         // if (!file.exists()) {  
    333.         // System.out.println("文件不存在,开始从远程服务器获取...");  
    334.         // download(pathString, pathString, sftp);  
    335.         // System.out.println("下载完成");  
    336.         // } else {  
    337.         // System.out.println("在本地找到文件");  
    338.         // }  
    339.         rmDir("", sftp, true);  
    340.         exit(sftp);  
    341.         System.exit(0);  
    342.     }  
    343. }  

    v0.31

    修正连接关闭,将关闭的方法改成私有,不允许使用者自行关闭(否则会导致连接池获取错误)
    优化删除文件及文件夹,先判断文件或文件夹是否存在,然后再删除
    [java] view plain copy
     
    1. package com.noryar.filesystem.utils;  
    2.   
    3. import java.io.ByteArrayOutputStream;  
    4. import java.io.File;  
    5. import java.io.FileOutputStream;  
    6. import java.util.ArrayList;  
    7. import java.util.HashMap;  
    8. import java.util.List;  
    9. import java.util.Map;  
    10. import java.util.Properties;  
    11. import java.util.Vector;  
    12.   
    13. import org.apache.commons.lang.StringUtils;  
    14.   
    15. import com.jcraft.jsch.Channel;  
    16. import com.jcraft.jsch.ChannelSftp;  
    17. import com.jcraft.jsch.ChannelSftp.LsEntry;  
    18. import com.jcraft.jsch.JSch;  
    19. import com.jcraft.jsch.JSchException;  
    20. import com.jcraft.jsch.Session;  
    21. import com.jcraft.jsch.SftpException;  
    22.   
    23. /** 
    24.  * 文件工具类.<br> 
    25.  * 1.所有的文件路径必须以'/'开头和结尾,否则路径最后一部分会被当做是文件名<br> 
    26.  * 2. @since version-0.3 方法出现异常的时候,<del>会关闭sftp连接(但是不会关闭session和channel)</del>(del @ version 0.31),异常会抛出<br> 
    27.  * @author Leon Lee 
    28.  */  
    29. public class SftpUtil {  
    30.   
    31.     /** 
    32.      * 文件路径前缀. /ddit-remote 
    33.      */  
    34.     private static final String PRE_FIX = "/test-noryar";  
    35.   
    36.     /** 
    37.      * sftp连接池. 
    38.      */  
    39.     private static final Map<String, Channel> SFTP_CHANNEL_POOL = new HashMap<String, Channel>();  
    40.   
    41.     /** 
    42.      * 获取sftp协议连接. 
    43.      * @param host 主机名 
    44.      * @param port 端口 
    45.      * @param username 用户名 
    46.      * @param password 密码 
    47.      * @return 连接对象 
    48.      * @throws JSchException 异常 
    49.      */  
    50.     public static ChannelSftp getSftpConnect(final String host, final int port, final String username,  
    51.             final String password) throws JSchException {  
    52.         Session sshSession = null;  
    53.         Channel channel = null;  
    54.         ChannelSftp sftp = null;  
    55.         String key = host + "," + port + "," + username + "," + password;  
    56.         if (null == SFTP_CHANNEL_POOL.get(key)) {  
    57.             JSch jsch = new JSch();  
    58.             jsch.getSession(username, host, port);  
    59.             sshSession = jsch.getSession(username, host, port);  
    60.             sshSession.setPassword(password);  
    61.             Properties sshConfig = new Properties();  
    62.             sshConfig.put("StrictHostKeyChecking", "no");  
    63.             sshSession.setConfig(sshConfig);  
    64.             sshSession.connect();  
    65.             channel = sshSession.openChannel("sftp");  
    66.             channel.connect();  
    67.             SFTP_CHANNEL_POOL.put(key, channel);  
    68.         } else {  
    69.             channel = SFTP_CHANNEL_POOL.get(key);  
    70.             sshSession = channel.getSession();  
    71.             if (!sshSession.isConnected())  
    72.                 sshSession.connect();  
    73.             if (!channel.isConnected())  
    74.                 channel.connect();  
    75.         }  
    76.         sftp = (ChannelSftp) channel;  
    77.         return sftp;  
    78.     }  
    79.   
    80.     /** 
    81.      * 下载文件-sftp协议. 
    82.      * @param downloadFile 下载的文件 
    83.      * @param saveFile 存在本地的路径 
    84.      * @param sftp sftp连接 
    85.      * @return 文件 
    86.      * @throws Exception 异常 
    87.      */  
    88.     public static File download(final String downloadFile, final String saveFile, final ChannelSftp sftp)  
    89.             throws Exception {  
    90.         FileOutputStream os = null;  
    91.         File file = new File(saveFile);  
    92.         try {  
    93.             if (!file.exists()) {  
    94.                 File parentFile = file.getParentFile();  
    95.                 if (!parentFile.exists()) {  
    96.                     parentFile.mkdirs();  
    97.                 }  
    98.                 file.createNewFile();  
    99.             }  
    100.             os = new FileOutputStream(file);  
    101.             List<String> list = formatPath(downloadFile);  
    102.             sftp.get(list.get(0) + list.get(1), os);  
    103.         } catch (Exception e) {  
    104.             throw e;  
    105.         } finally {  
    106.             os.close();  
    107.         }  
    108.         return file;  
    109.     }  
    110.   
    111.     /** 
    112.      * 下载文件-sftp协议. 
    113.      * @param downloadFile 下载的文件 
    114.      * @param saveFile 存在本地的路径 
    115.      * @param sftp sftp连接 
    116.      * @return 文件 byte[] 
    117.      * @throws Exception 异常 
    118.      */  
    119.     public static byte[] downloadAsByte(final String downloadFile, final ChannelSftp sftp) throws Exception {  
    120.         ByteArrayOutputStream os = new ByteArrayOutputStream();  
    121.         try {  
    122.             List<String> list = formatPath(downloadFile);  
    123.             sftp.get(list.get(0) + list.get(1), os);  
    124.         } catch (Exception e) {  
    125.             throw e;  
    126.         } finally {  
    127.             os.close();  
    128.         }  
    129.         return os.toByteArray();  
    130.     }  
    131.   
    132.     /** 
    133.      * 删除文件-sftp协议. 
    134.      * @param pathString 要删除的文件 
    135.      * @param sftp sftp连接 
    136.      * @throws SftpException 异常 
    137.      */  
    138.     public static void rmFile(final String pathString, final ChannelSftp sftp) throws SftpException {  
    139.         List<String> list = formatPath(pathString);  
    140.         String dir = list.get(0);  
    141.         String file = list.get(1);  
    142.         if (dirExist(dir + file, sftp)) {  
    143.             sftp.rm(list.get(0) + list.get(1));  
    144.         }  
    145.     }  
    146.   
    147.     /** 
    148.      * 删除文件夹-sftp协议.如果文件夹有内容,则会抛出异常. 
    149.      * @param pathString 文件夹路径 
    150.      * @param sftp sftp连接 
    151.      * @param resursion 递归删除 
    152.      * @throws SftpException 异常 
    153.      */  
    154.     public static void rmDir(final String pathString, final ChannelSftp sftp, final boolean recursion)  
    155.             throws SftpException {  
    156.         String fp = formatPath(pathString).get(0);  
    157.         if (dirExist(fp, sftp)) {  
    158.             if (recursion)  
    159.                 exeRmRec(fp, sftp);  
    160.             else  
    161.                 sftp.rmdir(fp);  
    162.         }  
    163.     }  
    164.   
    165.     /** 
    166.      * 递归删除执行. 
    167.      * @param pathString 文件路径 
    168.      * @param sftp sftp连接 
    169.      * @throws SftpException 
    170.      */  
    171.     private static void exeRmRec(final String pathString, final ChannelSftp sftp) throws SftpException {  
    172.         @SuppressWarnings("unchecked")  
    173.         Vector<LsEntry> vector = sftp.ls(pathString);  
    174.         if (vector.size() == 1) { // 文件,直接删除  
    175.             sftp.rm(pathString);  
    176.         } else if (vector.size() == 2) { // 空文件夹,直接删除  
    177.             sftp.rmdir(pathString);  
    178.         } else {  
    179.             String fileName = "";  
    180.             // 删除文件夹下所有文件  
    181.             for (LsEntry en : vector) {  
    182.                 fileName = en.getFilename();  
    183.                 if (".".equals(fileName) || "..".equals(fileName)) {  
    184.                     continue;  
    185.                 } else {  
    186.                     exeRmRec(pathString + "/" + fileName, sftp);  
    187.                 }  
    188.             }  
    189.             // 删除文件夹  
    190.             sftp.rmdir(pathString);  
    191.         }  
    192.     }  
    193.   
    194.     /** 
    195.      * 上传文件-sftp协议. 
    196.      * @param srcFile 源文件 
    197.      * @param dir 保存路径 
    198.      * @param fileName 保存文件名 
    199.      * @param sftp sftp连接 
    200.      * @throws Exception 异常 
    201.      */  
    202.     private static void uploadFile(final String srcFile, final String dir, final String fileName, final ChannelSftp sftp)  
    203.             throws SftpException {  
    204.         mkdir(dir, sftp);  
    205.         sftp.cd(dir);  
    206.         sftp.put(srcFile, fileName);  
    207.     }  
    208.   
    209.     /** 
    210.      * 上传文件-sftp协议. 
    211.      * @param srcFile 源文件路径,/xxx/xx.yy 或 x:/xxx/xxx.yy 
    212.      * @param sftp sftp连接 
    213.      * @return 上传成功与否 
    214.      * @throws SftpException 异常 
    215.      */  
    216.     public static boolean uploadFile(final String srcFile, final ChannelSftp sftp) throws SftpException {  
    217.         File file = new File(srcFile);  
    218.         if (file.exists()) {  
    219.             List<String> list = formatPath(srcFile);  
    220.             uploadFile(srcFile, list.get(0), list.get(1), sftp);  
    221.             return true;  
    222.         }  
    223.         return false;  
    224.     }  
    225.   
    226.     /** 
    227.      * 根据路径创建文件夹. 
    228.      * @param dir 路径 必须是 /xxx/xxx/ 不能就单独一个/ 
    229.      * @param sftp sftp连接 
    230.      * @throws SftpException 异常 
    231.      */  
    232.     public static boolean mkdir(final String dir, final ChannelSftp sftp) throws SftpException {  
    233.         if (StringUtils.isBlank(dir))  
    234.             return false;  
    235.         String md = dir.replaceAll("\\", "/");  
    236.         if (md.indexOf("/") != 0 || md.length() == 1)  
    237.             return false;  
    238.         return mkdirs(md, sftp);  
    239.     }  
    240.   
    241.     /** 
    242.      * 递归创建文件夹. 
    243.      * @param dir 路径 
    244.      * @param sftp sftp连接 
    245.      * @return 是否创建成功 
    246.      * @throws SftpException 异常 
    247.      */  
    248.     private static boolean mkdirs(final String dir, final ChannelSftp sftp) throws SftpException {  
    249.         String dirs = dir.substring(1, dir.length() - 1);  
    250.         String[] dirArr = dirs.split("/");  
    251.         String base = "";  
    252.         for (String d : dirArr) {  
    253.             base += "/" + d;  
    254.             if (dirExist(base + "/", sftp)) {  
    255.                 continue;  
    256.             } else {  
    257.                 sftp.mkdir(base + "/");  
    258.             }  
    259.         }  
    260.         return true;  
    261.     }  
    262.   
    263.     /** 
    264.      * 判断文件夹是否存在. 
    265.      * @param dir 文件夹路径, /xxx/xxx/ 
    266.      * @param sftp sftp协议 
    267.      * @return 是否存在 
    268.      */  
    269.     private static boolean dirExist(final String dir, final ChannelSftp sftp) {  
    270.         try {  
    271.             Vector<?> vector = sftp.ls(dir);  
    272.             if (null == vector)  
    273.                 return false;  
    274.             else  
    275.                 return true;  
    276.         } catch (SftpException e) {  
    277.             return false;  
    278.         }  
    279.     }  
    280.   
    281.     /** 
    282.      * 格式化路径. 
    283.      * @param srcPath 原路径. /xxx/xxx/xxx.yyy 或 X:/xxx/xxx/xxx.yy 
    284.      * @return list, 第一个是路径(/xxx/xxx/),第二个是文件名(xxx.yy) 
    285.      */  
    286.     public static List<String> formatPath(final String srcPath) {  
    287.         List<String> list = new ArrayList<String>(2);  
    288.         String repSrc = srcPath.replaceAll("\\", "/");  
    289.         int firstP = repSrc.indexOf("/");  
    290.         int lastP = repSrc.lastIndexOf("/");  
    291.         String fileName = lastP + 1 == repSrc.length() ? "" : repSrc.substring(lastP + 1);  
    292.         String dir = firstP == -1 ? "" : repSrc.substring(firstP, lastP);  
    293.         dir = PRE_FIX + (dir.length() == 1 ? dir : (dir + "/"));  
    294.         list.add(dir);  
    295.         list.add(fileName);  
    296.         return list;  
    297.     }  
    298.   
    299.     /** 
    300.      * 关闭协议-sftp协议.(关闭会导致连接池异常,因此不建议用户自定义关闭) 
    301.      * @param sftp sftp连接 
    302.      */  
    303.     private static void exit(final ChannelSftp sftp) {  
    304.         sftp.exit();  
    305.     }  
    306.   
    307.     public static void main(String[] args) throws Exception {  
    308.         ChannelSftp sftp = getSftpConnect("192.168.0.35", 22, "root", "root");  
    309.         // String pathString = "C:\test\ccc\Foxmail7.zip";  
    310.         // File file = new File(pathString);  
    311.         // System.out.println("上传文件开始...");  
    312.         // uploadFile(pathString, sftp);  
    313.         // System.out.println("上传成功,开始删除本地文件...");  
    314.         // file.delete();  
    315.         // System.out.println("删除完成,开始校验本地文件...");  
    316.         // if (!file.exists()) {  
    317.         // System.out.println("文件不存在,开始从远程服务器获取...");  
    318.         // download(pathString, pathString, sftp);  
    319.         // System.out.println("下载完成");  
    320.         // } else {  
    321.         // System.out.println("在本地找到文件");  
    322.         // }  
    323.         // rmDir("", sftp, true);  
    324.         String path = "E:\aaa.zip";  
    325.         File file = SftpUtil.download(path, path, sftp);  
    326.         // SftpUtil.exit(sftp);  
    327.         exit(sftp);  
    328.         System.exit(0);  
    329.     }  
    330. }  
  • 相关阅读:
    让服务器可以下载apk和ipa文件
    MVC第一次访问比较慢的解决方案
    [C#]记录程序耗时的方法【转发】
    uploadify上传带参数及接收参数的方法
    uploadify上传之前判断一个input输入框是否为空
    jgGrid获得的id值是主键的id而不是jqGrid的行号值
    jqGrid删除多行数据问题
    Linux下的微秒级定时器: usleep, nanosleep, select, pselect
    Linux平台延时之sleep、usleep、nanosleep、select比较
    Linux 高精確的時序(sleep, usleep,nanosleep) from:http://blog.sina.com.cn/s/blog_533ab41c0100htae.html
  • 原文地址:https://www.cnblogs.com/ceshi2016/p/7519788.html
Copyright © 2011-2022 走看看