jsch连接sftp工具类

1,283 阅读2分钟

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.ftp.FtpException;
import cn.hutool.extra.ssh.ChannelType;
import cn.hutool.extra.ssh.JschRuntimeException;
import com.jcraft.jsch.*;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;

/**
 * sftp下载工具类
 * @author mal
 * @date 2021-09-02 15:40
 */
public class SftpUtil {
    private static final Logger logger = LoggerFactory.getLogger(SftpUtil.class);

    private Session session;

    private ChannelSftp sftp;

    private String sshUser;

    private String sshPass;

    private String privateKeyPath;

    private String sshHost;

    private int sshPort;

    public SftpUtil(String sshUser, String sshPass, String sshHost, int sshPort) {
        this.sshUser = sshUser;
        this.sshPass = sshPass;
        this.sshHost = sshHost;
        this.sshPort = sshPort;
    }

    public SftpUtil(String sshUser, String sshHost, int sshPort, String privateKeyPath) {
        Assert.notEmpty(privateKeyPath, "privateKeyPath Path must be not empty!");

        this.sshUser = sshUser;
        this.sshHost = sshHost;
        this.sshPort = sshPort;
        this.privateKeyPath = privateKeyPath;
    }

    private SftpUtil() {

    }

    /**
     * 登录sftp
     */
    public void login() {
        Assert.notEmpty(sshUser, "sshUser Path must be not empty!");
        Assert.notEmpty(sshHost, "sshHost Path must be not empty!");
        Assert.isTrue(sshPort > 0, "SSH port must be > 0");

        JSch.setLogger(new JschLogPrint());
        final JSch jSch = new JSch();
        if (privateKeyPath != null) {
            try {
                jSch.addIdentity(privateKeyPath);
            } catch (JSchException e) {
                logger.error("login,addIdentity error", e);
                throw new JschRtException("sftp私钥地址[" + privateKeyPath + "]解析秘钥失败!请检查私钥文件是否存在");
            }
        }

        try {
            this.session = jSch.getSession(sshUser, sshHost, sshPort);
            // 设置第一次登录的时候提示,可选值:(ask | yes | no)
            this.session.setConfig("StrictHostKeyChecking", "no");
            this.session.setConfig("kex", "diffie-hellman-group1-sha1");
            this.session.connect(10000);
            logger.info("用户[{}]成功登录", sshUser);

        } catch (JSchException e) {
            logger.error("login,getSession error", e);
            throw new JschRtException("根据sshUser=[" + sshUser + "],sshHost=[" + sshHost + "],sshPort=[" + sshPort + "],创建session失败!");
        }
        if (sshPass != null) {
            session.setPassword(sshPass);
        }

        Channel channel;
        try {
            channel = session.openChannel(ChannelType.SFTP.getValue());
            channel.connect(10000);
        } catch (JSchException e) {
            logger.error("login,openChannel error!", e);
            throw new JschRtException("sftp打开消息通道失败!");
        }
        sftp = (ChannelSftp) channel;
    }


    /**
     *
     * @param directory
     * @return
     * @throws SftpRtException
     */
    public boolean cd(String directory) throws FtpException {
        if (StrUtil.isBlank(directory)) {
            // 当前目录
            return true;
        }
        try {
            sftp.cd(directory.replace('\', '/'));
            return true;
        } catch (SftpException e) {
            throw new SftpRtException(e);
        }
    }

    /**
     * 判断远程SFTP服务器上是否存在某个文件
     * @param directory 目录
     * @param fileName 文件名
     * @return 是否存在
     */
    public boolean isExists(String directory, String fileName){

        boolean isHave = false;
        try {
            if (StringUtils.isNotBlank(directory)) {
                sftp.cd(directory);
            }
            SftpATTRS attrs = sftp.stat(fileName);
            if(attrs != null){
                isHave = true;
            }
        } catch (Exception e) {
            logger.error("isExists,directory = [" + directory + "], fileName = [" + fileName + "],error", e);
        }
        return  isHave;
    }

    /**
     * 下载文件
     * @param directory 下载目录
     * @param downloadFile 下载的文件名
     * @param saveFile 保存的文件的绝对路径
     * @throws SftpException
     */
    public void download(String directory, String downloadFile, String saveFile) throws SftpException {
        if (directory != null && directory.length() > 0) {
            sftp.cd(directory);
        }
        sftp.get(downloadFile, saveFile);


    }


    /**
     * 下载文件
     * @param directory 下载目录
     * @param downloadFile 下载的文件名
     * @param saveFile 保存的文件的绝对路径
     * @throws SftpException
     */
    public void download(String directory, String downloadFile, File saveFile) throws SftpException, IOException {
        logger.info("download start,directory = 【{}】, downloadFile = 【{}】, saveFile = 【{}】", directory, downloadFile, saveFile.getAbsolutePath());
        if (directory != null && directory.length() > 0) {
            sftp.cd(directory);
        }
        try (OutputStream out = new FileOutputStream(saveFile)){
            sftp.get(downloadFile, out);
            logger.info("download end,directory = 【{}】, downloadFile = 【{}】, saveFile = 【{}】", directory, downloadFile, saveFile.getAbsolutePath());
        }


    }

    /**
     * 下载文件
     * @param directory 下载目录
     * @param downloadFile 下载的文件名
     * @param out 目标流
     */
    public void download(String directory, String downloadFile, OutputStream out) throws SftpException {
        if (directory != null && directory.length() > 0) {
            sftp.cd(directory);
        }
        sftp.get(downloadFile, out);

    }

    /**
     * 下载文件
     * @param directory 下载目录
     * @param downloadFile 下载的文件名
     * @return 字节数组
     */
    public byte[] download(String directory, String downloadFile) throws SftpException, IOException {
        if (directory != null && directory.length() > 0) {
            sftp.cd(directory);
        }
        InputStream is = sftp.get(downloadFile);
        return IOUtils.toByteArray(is);
    }


    /**
     * 获取HOME路径
     * @return
     */
    public String home() {
        try {
            return sftp.getHome();
        } catch (SftpException e) {
            throw new JschRuntimeException(e);
        }
    }




    /**
     * 关闭连接 server
     */
    public void logout(){
        if (sftp != null) {
            if (sftp.isConnected()) {
                sftp.disconnect();
            }
        }
        if (session != null) {
            if (session.isConnected()) {
                session.disconnect();
            }
        }
    }

    class JschLogPrint implements com.jcraft.jsch.Logger{
        @Override
        public boolean isEnabled(int level) {
            return true;
        }

        @Override
        public void log(int level, String message) {
            logger.info(message);
        }
    }


}

这里边使用到了hutool 工具类

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.7.2</version>
</dependency>