【基于java的sftp操作工具类】


前言

项目开发过程中,多少可能会涉及到ftp, sftp文件传输、转存与恢复的操作。小生推荐使用sftp, 至于二者的区别, 在此不多赘述。


一、jsch简介

摘: JSch是Java Secure Channel的缩写。JSch是一个SSH2的纯Java实现。它允许你连接到一个SSH服务器,并且可以使用端口转发,X11转发,文件传输等,当然你也可以集成它的功能到你自己的应用程序。
jsch官网API:jsch官网API.

使用:

  • new一个JSch对象
  • 从JSch对象中获取Session,用于连接,并设置连接信息(两种方式:一是用户名+密码;二是用户名+privatekey+passphrase。第二种方式要在第1步设置,即jsch.addIdentity(xxx))
  • 使用session对象调用opnChannel("xxx")打开通信信道,并连接
  • 后面就是基于不同的channel进行不同的操作

二、sftp工具类使用步骤

1.添加maven依赖

<!-- https://mvnrepository.com/artifact/com.jcraft/jsch -->
<dependency>
    <groupId>com.jcraft</groupId>
    <artifactId>jsch</artifactId>
    <version>0.1.54</version>
</dependency>

2.工具类代码

package com.ctsi.fileStore.util;

import com.ctsi.fileStore.common.constant.StringConstant;
import com.jcraft.jsch.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.IOUtils;

import java.io.*;
import java.util.List;
import java.util.Properties;
import java.util.Vector;

/**
 * SFTP工具类
 *
 * @Author 屋顶上的蜗牛·
 * @Date 2021-11-29
 */
@Slf4j
public class SftpUtil {
    private ChannelSftp sftp;

    private Session session;

    /**
     * SFTP 登录用户名
     */
    private String username;

    /**
     * SFTP 登录密码
     */
    private String password;

    /**
     * 私钥
     */
    private String privateKey;

    /**
     * SFTP 服务器地址IP地址
     */
    private String host;

    /**
     * SFTP 端口
     */
    private int port;

    /**
     * 超时时间3秒
     */
    private static final int CONNECT_TIME_OUT = 3000;

    /**
     * 构造基于密码认证的sftp对象
     */
    public SftpUtil(String username, String password, String host, int port) {
        this.username = username;
        this.password = password;
        this.host = host;
        this.port = port;
    }

    /**
     * 构造基于秘钥认证的sftp对象
     */
    public SftpUtil(String username, String host, int port, String privateKey) {
        this.username = username;
        this.host = host;
        this.port = port;
        this.privateKey = privateKey;
    }

    public SftpUtil() {
    }

    /**
     * 连接sftp服务器
     */
    public void login() {
        try {
            JSch jsch = new JSch();
            if (StringUtils.isNotEmpty(privateKey)) {
                // 设置私钥
                jsch.addIdentity(privateKey);
            }

            session = jsch.getSession(username, host, port);

            if (StringUtils.isNotEmpty(password)) {
                session.setPassword(password);
            }
            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");

            session.setConfig(config);
            session.connect(CONNECT_TIME_OUT);

            Channel channel = session.openChannel("sftp");
            channel.connect();

            sftp = (ChannelSftp) channel;
            log.info("sftp服务器登录成功...");
        } catch (JSchException e) {
            log.info("sftp服务器登录失败, 失败信息为: {}", e.getMessage());
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    /**
     * 关闭连接 server
     */
    public void logout() {
        if (Objects.nonNull(sftp)) {
            if (sftp.isConnected()) {
                sftp.disconnect();
            }
        }
        if (Objects.nonNull(session)) {
            if (session.isConnected()) {
                session.disconnect();
            }
        }
        log.info("sftp服务器登出成功...");
    }

    /**
     * 将输入流的数据上传到sftp作为文件。文件完整路径=basePath+directory
     *
     * @param basePath     服务器的基础路径
     * @param directory    上传到该目录
     * @param sftpFileName sftp端文件名
     * @param input        输入流
     */
    public void upload(String basePath, String directory, String sftpFileName, InputStream input) throws SftpException, IOException {
        String allPath;
        if (StringUtils.endsWith(basePath, "/")) {
            allPath = basePath + directory;
        } else {
            allPath = basePath + "/" + directory;
        }
        log.info("文件存放sftp服务器根目录为: {}, 存放的完整目录为: {}, sftp端文件名为: {}", basePath, allPath, sftpFileName);
        try {
            sftp.cd(allPath);
        } catch (SftpException e) {
            //目录不存在,则创建文件夹
            String[] dirs = allPath.split("/");
            String tempPath;
            StringBuilder tempPathBuilder = new StringBuilder();
            for (String dir : dirs) {
                if (StringUtils.isEmpty(dir)) {
                    continue;
                }
                tempPathBuilder.append("/").append(dir);
                tempPath = tempPathBuilder.toString();
                try {
                    sftp.cd(tempPath);
                } catch (SftpException ex) {
                    sftp.mkdir(tempPath);
                    sftp.cd(tempPath);
                }
            }
        }

        //上传文件
        sftp.put(input, sftpFileName);
        input.close();
    }

    /**
     * 下载文件
     *
     * @param directory    下载目录
     * @param downloadFile 下载的文件名
     * @param saveFile     存在本地的路径
     */
    public void download(String directory, String downloadFile, String saveFile) throws SftpException,
            FileNotFoundException {
        log.info("sftp文件下载目录为: {}, 待下载的文件名为: {}, 存放至本地的全路径为: {}", directory, downloadFile, saveFile);
        if (StringUtils.isNotEmpty(directory)) {
            sftp.cd(directory);
        }
        File file = new File(saveFile);
        sftp.get(downloadFile, new FileOutputStream(file));
    }

    /**
     * 下载文件
     *
     * @param directory    下载目录
     * @param downloadFile 下载的文件名
     * @return 字节数组
     */
    public byte[] download(String directory, String downloadFile) throws SftpException, IOException {
        log.info("sftp文件下载目录为: {}, 待下载的文件名为: {}", directory, downloadFile);
        if (StringUtils.isNotEmpty(directory)) {
            sftp.cd(directory);
        }
        InputStream is = sftp.get(downloadFile);
        return IOUtils.toByteArray(is);
    }

    /**
     * 下载文件
     *
     * @param directory    下载目录
     * @param downloadFile 下载的文件名
     * @return 输入流
     */
    public InputStream downloadStream(String directory, String downloadFile) throws SftpException {
        log.info("sftp文件下载目录为: {}, 待下载的文件名为: {}", directory, downloadFile);
        if (StringUtils.isNotEmpty(directory)) {
            sftp.cd(directory);
        }
        return sftp.get(downloadFile);
    }

    /**
     * 删除文件
     *
     * @param directory   要删除文件所在目录
     * @param deleteFiles 要删除的多个文件名
     */
    public void delete(String directory, List<String> deleteFiles) {
        if (CollectionUtils.isEmpty(deleteFiles)) {
            log.info("没有待删除的文件名...");
            return;
        }

        log.info("待删除的文件所在目录为: {}", directory);
        try {
            sftp.cd(directory);
        } catch (SftpException e) {
            log.error("进入要删除文件所在目录失败, 失败信息为: {}", directory);
            throw new RuntimeException("进入要删除文件所在目录失败");
        }
        deleteFiles.forEach(each -> {
            try {
                sftp.rm(each);
                log.info("删除文件[{}]成功...", each);
            } catch (SftpException e) {
                log.info("删除文件时, [{}]文件名不存在, 跳过删除...", each);
            }
        });
    }

    /**
     * 删除文件
     *
     * @param directory  要删除文件所在目录
     * @param deleteFile 要删除的文件名
     */
    public void delete(String directory, String deleteFile) {
        if (StringUtils.isEmpty(deleteFile)) {
            log.info("待删除的文件名为空...");
            return;
        }

        log.info("待删除的文件所在目录为: {}", directory);
        try {
            sftp.cd(directory);
        } catch (SftpException e) {
            log.error("进入要删除文件所在目录失败, 失败信息为: {}", directory);
            throw new RuntimeException("进入要删除文件所在目录失败");
        }
        try {
            sftp.rm(deleteFile);
            log.info("删除文件[{}]成功...", deleteFile);
        } catch (SftpException e) {
            log.info("删除文件时, [{}]文件名不存在, 跳过删除...", deleteFile);
        }
    }

    /**
     * 列出目录下的文件
     *
     * @param directory 要列出的目录
     */
    public Vector<?> listFiles(String directory) throws SftpException {
        return sftp.ls(directory);
    }
}

3.调用测试

public static void main(String[] args) throws SftpException, IOException {
    SftpUtil sftp = new SftpUtil("root", "123456", "127.0.0.1", 22);
    sftp.login();

    // 上传
    File file = new File("***");
    InputStream is = new FileInputStream(file);
    sftp.upload("***", "***", "***", is);

    // 下载
    sftp.download("***", "***", "***");

    // 删除
    sftp.delete("***", Lists.newArrayList("***", "***"));
    
    sftp.logout();
}

三、结语

以上便是java中使用sftp的常用方法, 其他方法, 博友们可自行丰富。若有出入的地方, 欢迎博友们指正。在下感激不尽!

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值