利用sftp进行上传、单个下载、批量下载和删除

 最近公司让用SFTP用来和远端进行交互,学习了;一段时间sftp,现在将代码干货献上,希望对大家能够有所帮助:

1. 在src/com/zkr/sftp(建议建立在src下)下建立sftp.properties文件:

               sftp.host=127.0.0.1
               sftp.port=22
               sftp.username=zhen
               sftp.password=12345
               sftp.timeout=60000
               sftp.privateKey
               sftp.passphrase

2. 创建SFTPUtils类,完成上传、下载、删除功能:

package com.zkr.sftp;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream.GetField;
import java.util.Iterator;
import java.util.Properties;
import java.util.Vector;

import com.enterprisedt.util.debug.Logger;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpATTRS;
import com.jcraft.jsch.SftpException;

public class SftpUtils {

    private static final Logger log = Logger.getLogger(SftpUtils.class); // 用来记录日志

    Session session = null;

    String privateKey = null;
    String passphrase = null;
    String host = null; // sftp服务器的IP
    String username = null; // 用户名
    String password = null; // 密码
    int timeout = 60000; // 超时时间
    int port = 22; // 端口号

    /**
     * 在构造函数中读取配置文件
     */
    public SftpUtils() {

        File file = new File("src/com/zkr/sftp/sftp.properties");
        InputStream in = null;

        try {
            in = new FileInputStream(file);
        } catch (FileNotFoundException e) {
            log.error("异常:文件没有找到", e);
        }

        Properties prop = new Properties();
        try {
            prop.load(in);
        } catch (IOException e) {
            log.error("异常:加载配置文件失败", e);
        }

        // 读取配置文件信息
        host = prop.getProperty("sftp.host");
        port = Integer.parseInt(prop.getProperty("sftp.port"));
        username = prop.getProperty("sftp.username");
        password = prop.getProperty("sftp.password");
        timeout = Integer.parseInt(prop.getProperty("sftp.timeout"));
        privateKey = prop.getProperty("sftp.privateKey");
        passphrase = prop.getProperty("sftp.passphrase");
        log.info("try to connect to " + host + ",username:" + username
                + ",password:" + password + ",port:" + port);
    }

    /**
     * 得到连接
     * 
     * @return
     */
    private ChannelSftp GetConnectSftp() {
        JSch jsch = new JSch();
        ChannelSftp channelSftp = null;
        try {
            if (privateKey != null && !"".equals(privateKey)) {
                // 使用密钥验证方式,密钥可以使有口令的密钥,也可以是没有口令的密钥
                if (passphrase != null && "".equals(passphrase)) {
                    jsch.addIdentity(privateKey, passphrase);
                } else {
                    jsch.addIdentity(privateKey);
                }
            }
            session = jsch.getSession(username, host, port);
            // 设置密码
            if (password != null && !"".equals(password)) {
                session.setPassword(password);
            }
            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");// do not verify host
            // 为session对象设置properties
            session.setConfig(config);
            // 设置超时
            session.setTimeout(timeout);
            //session.setServerAliveInterval(92000);
            session.connect();
            // 参数sftp指明要打开的连接是sftp连接
            channelSftp = (ChannelSftp) session.openChannel("sftp");
            channelSftp.connect();
            System.out.println("连接成功");
        } catch (JSchException e) {
            // log.error("异常:连接失败",e);
            System.out.println("连接失败");
        }
        return channelSftp;

    }

    /**
     * 下载
     * 
     * @param directory
     *            源文件在服务器的路径,不包括文件名
     * @param srcFilename
     *            源文件名
     * @param dstPath
     *            下载到本地的目标路径
     */
    public void download(String directory, String srcFilename, String dstPath) {
        ChannelSftp channelSftp = null;
        // 得到连接
        channelSftp = GetConnectSftp();
        try {
            if (channelSftp != null) {
                // 进入服务器相应路径
                channelSftp.cd(directory);
                // 进行下载
                channelSftp.get(srcFilename, dstPath);
                log.info("下载成功:" + srcFilename);
            }
        } catch (SftpException e) {
            log.error("异常:下载失败:" + srcFilename, e);
            e.printStackTrace();
        } finally {
            // 释放连接
            disconnected(channelSftp);
        }

    }

    /**
     * 下载 为批量下载做准备
     * 
     * @param directory        源文件在服务器的路径,不包括文件名
     * @param srcFilename    源文件名
     * @param dstPath        下载到本地的目标路径
     * @param channelSftp
     */
    private void download(String directory, String srcFilename, String dstPath,
            ChannelSftp channelSftp) {
        try {
            if (channelSftp != null) {
                channelSftp.cd(directory);
                channelSftp.get(srcFilename, dstPath);
            }
        } catch (SftpException e) {
            log.error("异常:  下载失败:" + directory + "/" + srcFilename, e);
            e.printStackTrace();
        }

    }

    /**
     * 批量下载
     * @param pathName    服务器端目录
     * @param dstPath    本地目录
     */
    public void batchDownload(String pathName, String dstPath) {
        ChannelSftp channelSftp = null;
        // 得到连接
        channelSftp = GetConnectSftp();
        //批量下载管理
        batchDownMag(pathName, dstPath, channelSftp);
        //断开连接
        disconnected(channelSftp);

    }

    /**
     * 上传
     * 
     * @param directory
     *            上传目录,不包括文件名
     * @param srcPath
     *            本地文件路径,包括文件名
     * @param dstFilename
     *            在服务器中对上传文件进行命名
     */
    public void upload(String directory, String srcPath, String dstFilename) {
        ChannelSftp channelSftp = null;
        // 获取连接
        channelSftp = GetConnectSftp();
        if (channelSftp != null) {
            // 若存在directory这个目录,则进入其中;若不存在,则先在服务器先创建该目录并进入
            createDir(directory, channelSftp);
            try {
                channelSftp.put(srcPath, dstFilename);
                log.info("上传成功:" + directory);
            } catch (SftpException e) {
                log.error("异常:上传失败:" + directory, e);
                e.printStackTrace();
            } finally {
                // 释放连接
                disconnected(channelSftp);
            }
        }
    }

    /**
     * 删除文件
     * 
     * @param directory
     *            要删除文件所在目录,不包括文件名
     * @param deleteFilename
     *            要删除的文件名
     */
    public void delete(String directory, String deleteFilename) {
        ChannelSftp channelSftp = null;
        // 获取连接
        channelSftp = GetConnectSftp();
        if (channelSftp != null) {
            try {
                // 进入服务器相应目录
                channelSftp.cd(directory);
                // 删除文件
                channelSftp.rm(deleteFilename);
            } catch (SftpException e) {
                log.error("异常:删除失败:" + deleteFilename, e);
                e.printStackTrace();
            } finally {
                // 释放连接
                disconnected(channelSftp);
            }

        }
    }

    /**
     * 打开或进入目录
     * 
     * @param directory
     * @param channelsftp
     * @return
     */
    private boolean openDir(String directory, ChannelSftp channelsftp) {
        try {
            channelsftp.cd(directory);
            return true;
        } catch (SftpException e) {
            log.error("异常: 该目录不存在:" + directory, e);
            // e.printStackTrace();
            return false;
        }
    }

    /**
     * 批量下载管理
     * 
     * @param pathName
     *            服务器端地址
     * @param dstPath
     *            本地地址
     * @param channelSftp
     */
    private void batchDownMag(String pathName, String dstPath,
            ChannelSftp channelSftp) {
        // 确保服务端地址是绝对地址
        if (!pathName.startsWith("/")) {
            pathName = "/" + pathName;
        }
        // 目录标志符,若为有效地址,则为true,否则为false
        boolean flag = openDir(pathName, channelSftp);
        if (flag) {
            try {
                Vector vv = channelSftp.ls(pathName);
                if (vv == null && vv.size() == 0) {
                    return;
                } else {
                    // 遍历当前目录所有文件及子文件夹
                    for (Object object : vv) {
                        ChannelSftp.LsEntry entry = (ChannelSftp.LsEntry) object;
                        // 得到当前项的名称(可能是文件名,也可能是文件夹名)
                        String filename = entry.getFilename();
                        // 去除无关项
                        if (".".equals(filename) || "..".equals(filename)) {
                            continue;
                        }
                        if (openDir(pathName + "/" + filename, channelSftp)) {
                            // 能打开,说明是目录,接着遍历
                            String dstPathChild = dstPath + "/" + filename;
                            File file = new File(dstPathChild);
                            //若本地不存在该目录,则进行创建
                            if (!file.isDirectory()) {
                                file.mkdirs();
                            }
                            //进行递归
                            batchDownMag(pathName + "/" + filename,
                                    dstPathChild, channelSftp);
                        } else {
                            
                            download(pathName, filename, dstPath, channelSftp);
                        }
                    }
                }
            } catch (SftpException e) {
                log.error("遍历目录失败:" + pathName, e);
            }
        } else {
            log.info("对应的目录" + pathName + "不存在!");
        }

    }

    /**
     * 断开连接
     * 
     * @param channelSftp
     */
    private void disconnected(ChannelSftp channelSftp) {
        if (channelSftp != null) {
            try {
                // 判断session是否连接
                if (channelSftp.getSession().isConnected()) {
                    // 若连接,则释放连接
                    channelSftp.getSession().disconnect();
                }
            } catch (JSchException e) {
                log.error("异常:无法获取session", e);
                e.printStackTrace();
            }
            // 判断channelSftp是否连接
            if (channelSftp.isConnected()) {
                // 若连接,则释放连接
                channelSftp.disconnect();
            }
        }
    }

    /**
     * 若存在相应目录,则进入该目录中 若不存在相应目录,则会在服务器中创建并进入该目录中
     * 
     * @param directory
     * @param channelSftp
     */
    private void createDir(String directory, ChannelSftp channelSftp) {
        try {
            // 判断是否存在相应目录
            if (isDirExist(directory, channelSftp)) {
                // 若存在,则进入并设置为当前目录
                channelSftp.cd(directory);
                return;
            }
            // 对路径进行拆分
            String[] pathArray = directory.split("/");
            // 加"/"设置为绝对路径
            StringBuffer filePath = new StringBuffer("/");
            for (String path : pathArray) {
                // 若directory为绝对路径,则为true
                if (path.equals("")) {
                    continue;
                }
                filePath.append(path + "/");
                if (isDirExist(filePath.toString(), channelSftp)) {
                    channelSftp.cd(filePath.toString());
                } else {
                    // 建立目录
                    channelSftp.mkdir(filePath.toString());
                    // 进入并设置为当前路径
                    channelSftp.cd(filePath.toString());
                }
            }

        } catch (SftpException e) {
            log.error("异常:创建路径错误:" + directory, e);
            e.printStackTrace();
        }
    }

    /**
     * 判断目录是否存在
     * 
     * @param directory
     * @param channelSfrp
     * @return
     */
    private boolean isDirExist(String directory, ChannelSftp channelSftp) {
        boolean isDirExistFlag = false;
        try {
            SftpATTRS sftpATTRS = channelSftp.lstat(directory);
            isDirExistFlag = true;
            return sftpATTRS.isDir();
        } catch (SftpException e) {
            if (e.getMessage().toLowerCase().equals("no such file")) {
                isDirExistFlag = false;
            }
            e.printStackTrace();
        }
        return isDirExistFlag;

    }

}

3.写测试类进行测试

package com.zkr.sftp;

import com.jcraft.jsch.ChannelSftp;

public class Demo {

       @Test
       public void test1() throws Exception {
        SftpUtils sftputils = new SftpUtils();

        String directory = "sdf/史蒂夫";
        String srcPath = "E:/111/花好月不圆/若只如初见.txt";
        String dstFilename = "情深却只增悲痛.txt";
        String srcFilename = "秋风何时悲画卷.xlsx";
        String dstPath = "E:/111/zhen";
        String deleteFilename = "[www.java1234.com]redis设计与实现(第二版).pdf";
        
        //将本地中的E:/111/花好月不圆/若只如初见.txt上传到sftp服务器中的sdf/史蒂夫的目录中,并起名为情深却只增悲痛.txt
        sftputils.upload(directory, srcPath, dstFilename);
        //将sftp服务器中的sdf/史蒂夫/秋风何时悲画卷.xlsx下载到本地的E:/111/zhen目录中
        sftputils.download(directory, srcFilename, dstPath);
        //删除sftp服务器中的sdf/史蒂夫/[www.java1234.com]redis设计与实现(第二版).pdf
        sftputils.delete(directory, deleteFilename);
    }

//测试批量下载功能

   @Test
    public void test2(){
        SftpUtils sftpUtils=new SftpUtils();
        String pathName="/sdf/11/史蒂夫";
        String dstPath="E:/33";
        sftpUtils.batchDownload(pathName, dstPath);
        
    }

}
 

你可能感兴趣的:(利用sftp进行上传、单个下载、批量下载和删除)