SpringBoot 获取 SFTP文件服务器文件【一看就会】

springBoot 整合 SFTP

一、引入依赖

<!-- sftp -->
<dependency>
    <groupId>com.jcraft</groupId>
    <artifactId>jsch</artifactId>
    <version>0.1.55</version>
</dependency>

二、增加配置项

sftp:
  protocol: xxxx
  host: xxxxx
  port: 22 # 端口
  username: root
  password: ******

三、编写SftpUtils

创建SFTP 连接

/**
 * 创建SFTP 连接
 *
 * @param userName userName
 * @param host     host
 * @param port     port
 * @param password password
 * @return
 * @throws JSchException
 */
public static ChannelSftp createSftp(String userName, String host, int port, String password) throws JSchException {
    log.error("createSftp. userName:{}, host:{}, port:{}, password:{}", userName, host, port, password);
    JSch jsch = new JSch();
    // 获取session
    Session session = jsch.getSession(userName, host, port);
    // 设置密码
    session.setPassword(password);
    session.setConfig("StrictHostKeyChecking", "no");
    session.connect();

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

    return (ChannelSftp) channel;
}

关闭SFTP的连接

/**
 * 关闭SFTP的连接
 *
 * @param channelSftp sftp
 */
public static void closeSftp(ChannelSftp channelSftp) {
    try {
        if (channelSftp != null) {
            if (channelSftp.isConnected()) {
                channelSftp.disconnect();
            } else if (channelSftp.isClosed()) {
                log.error("sftp is closed already.");
            }

            if (null != channelSftp.getSession()) {
                channelSftp.getSession().disconnect();
            }
        }
    } catch (JSchException e) {
        e.printStackTrace();
    }
}

判断文件路径在sftp服务器是否存在

/**
 * 判断文件路径在sftp服务器是否存在
 *
 * @param sftp          sftp
 * @param directoryPath 文件夹路径 如: roster/test.html
 * @return
 */
public static boolean isDirExist(ChannelSftp sftp, String directoryPath) {
    if (StringUtils.isEmpty(directoryPath)) {
        log.error("isDirExist directoryPath is empty.");
        return false;
    }
    try {
        // 判断文件在sftp服务器是否存在
        SftpATTRS lstat = sftp.lstat(directoryPath);
        if (lstat.isDir()) {
            return true;
        }
    } catch (SftpException e) {
        log.error("isDirExist error. e:{}", e.toString());
        e.printStackTrace();
    }
    return false;
}

创建一个文件夹

/**
 * 创建一个文件夹
 *
 * @param sftp       sftp
 * @param createPath 创建目录(以 / 结尾)
 * @return
 */
public static boolean createDir(ChannelSftp sftp, String createPath) {
    // 创建目录不为空
    if (StringUtils.isEmpty(createPath)) {
        log.error("createDir createPath is empty.");
        return false;
    }
    // 创建目录以 / 结尾
    boolean endsWith = createPath.endsWith("/");
    if (!endsWith) {
        log.error("createDir createPath endsWith is not 【/】.");
        return false;
    }
    // 如果已经存在此目录则直接返回成功
    if (isDirExist(sftp, createPath)) {
        log.error("createDir createPath isDirExist is true.");
        return true;
    }
    // 创建目录 mkdir
    try {
        String[] split = createPath.split("/");
        StringBuilder sb = new StringBuilder();
        for (String path : split) {
            sb.append(path).append("/");
            String sbPath = sb.toString();
            if (!isDirExist(sftp, sbPath)) {
                sftp.mkdir(sbPath);
            }
        }
        return true;
    } catch (SftpException e) {
        log.error("createDir mkdir error. e:{}", e.toString());
        e.printStackTrace();
    }
    return false;
}

删除一个文件夹

/**
 * 删除一个文件夹
 *
 * @param sftp       sftp
 * @param deletePath 删除目录(以 / 结尾)
 * @return
 */
public static boolean deleteDir(ChannelSftp sftp, String deletePath) {
    // 删除目录不为空
    if (StringUtils.isEmpty(deletePath)) {
        log.error("deleteDir deletePath is empty.");
        return false;
    }
    // 删除目录以 / 结尾
    boolean endsWith = deletePath.endsWith("/");
    if (!endsWith) {
        log.error("deleteDir deletePath endsWith is not 【/】.");
        return false;
    }
    // 如果不存在此目录则直接返回成功
    if (!isDirExist(sftp, deletePath)) {
        log.error("deleteDir deletePath isDirExist is false.");
        return true;
    }
    // 删除
    try {
        sftp.rmdir(deletePath);
        return true;
    } catch (SftpException e) {
        log.error("deleteDir rm error. e:{}", e.toString());
        e.printStackTrace();
    }
    return false;
}

删除文件

/**
 * 删除文件
 *
 * @param sftp     sftp
 * @param filePath /roster
 * @param fileName /test.html
 * @return
 */
public static boolean deleteFile(ChannelSftp sftp, String filePath, String fileName) {
    // 参数校验
    if (StringUtils.isEmpty(filePath) || StringUtils.isEmpty(fileName)) {
        log.error("deleteFile path is empty. filePath:{}, filePath:{}", filePath, fileName);
        return false;
    }
    // 目录 及 文件名称
    String path = filePath + fileName;
    log.error("deleteFile path:{}", path);

    // 判断目录是否存在
    if (!isDirExist(sftp, filePath)) {
        log.error("deleteFile filePath isDirExist is false. path:{}", path);
        return false;
    }

    // 删除
    try {
        sftp.rm(path);
        return true;
    } catch (SftpException e) {
        log.error("deleteFile rm error. e:{}", e.toString());
        e.printStackTrace();
    }
    return false;
}

文件上传

/**
 * 文件上传
 *
 * @param sftp           sftp
 * @param fileStream     文件输入流
 * @param uploadFilePath 上传文件夹路径
 * @param uploadFileName 上传文件名称
 * @return
 */
public static boolean uploadFile(ChannelSftp sftp, InputStream fileStream, String uploadFilePath, String uploadFileName) {
    // 参数校验
    if (Objects.isNull(fileStream) || StringUtils.isEmpty(uploadFilePath) || StringUtils.isEmpty(uploadFileName)) {
        log.error("uploadFile data is empty. fileStream:{}, uploadFilePath:{}, uploadFileName:{}", fileStream, uploadFilePath, uploadFileName);
        return false;
    }

    // 目录 及 文件名称
    String path = uploadFilePath + uploadFileName;
    log.error("uploadFile uploadFilePath:{}", path);

    // 判断上传目录是否存在
    if (!isDirExist(sftp, uploadFilePath)) {
        log.error("uploadFile uploadFilePath isDirExist is false. path:{}", path);
        return false;
    }

    // 上传
    try {
        sftp.put(fileStream, path);
        return true;
    } catch (SftpException e) {
        log.error("uploadFile put error. e:{}", e.toString());
        e.printStackTrace();
    }

    return false;
}

读取文件内容

/**
 * 获取指定sftp服务器上 指定目录下 指定文件名(含后缀) 的文本内容
 *
 * @param sftp     sftp
 * @param filePath 文件目录
 * @param fileName 文件名称
 * @return
 */
public static String getTextFileContent(ChannelSftp sftp, String filePath, String fileName) {
    // 目录 及 文件名称
    String path = filePath + fileName;
    log.error("getTextFileContent. path:{}", path);

    //限制文件类型
    List<String> fileTypeStrList = Lists.newArrayList("txt", "html");
    String[] split = fileName.split("\\.");
    String fileTypeStr = split[split.length - 1];
    if (!fileTypeStrList.contains(fileTypeStr)) {
        log.error("getTextFileContent fileTypeStr is not contains. path:{}", path);
        return StringUtils.EMPTY;
    }

    StringBuilder stringBuilder = new StringBuilder();
    try {
        // 判断查看目录是否存在
        if (!isDirExist(sftp, filePath)) {
            log.error("getTextFileContent filePath isDirExist is false. path:{}", path);
            return StringUtils.EMPTY;
        }
        // 获取input stream
        InputStream inputStream = sftp.get(path);
        InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
        String line;
        BufferedReader br = new BufferedReader(inputStreamReader);
        while ((line = br.readLine()) != null) {
            stringBuilder.append(line);
        }
    } catch (SftpException | IOException e) {
        log.error("getTextFileContent. e:{}", e.toString());
        e.printStackTrace();
    }
    return stringBuilder.toString();
}

完整SftpUtils类

package com.joker.cloud.linserver.conf.sftp;

import com.google.common.collect.Lists;
import com.jcraft.jsch.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Objects;

/**
 * SftpUtils
 *
 * @author joker
 * @version 1.0
 * 2024/3/28 10:42
 **/

@Slf4j
@Service
public class SftpUtils {


    /**
     * 创建SFTP 连接
     *
     * @param userName userName
     * @param host     host
     * @param port     port
     * @param password password
     * @return
     * @throws JSchException
     */
    public static ChannelSftp createSftp(String userName, String host, int port, String password) throws JSchException {
        log.error("createSftp. userName:{}, host:{}, port:{}, password:{}", userName, host, port, password);
        JSch jsch = new JSch();
        // 获取session
        Session session = jsch.getSession(userName, host, port);
        // 设置密码
        session.setPassword(password);
        session.setConfig("StrictHostKeyChecking", "no");
        session.connect();

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

        return (ChannelSftp) channel;
    }


    /**
     * 关闭SFTP的连接
     *
     * @param channelSftp sftp
     */
    public static void closeSftp(ChannelSftp channelSftp) {
        try {
            if (channelSftp != null) {
                if (channelSftp.isConnected()) {
                    channelSftp.disconnect();
                } else if (channelSftp.isClosed()) {
                    log.error("sftp is closed already.");
                }

                if (null != channelSftp.getSession()) {
                    channelSftp.getSession().disconnect();
                }
            }
        } catch (JSchException e) {
            e.printStackTrace();
        }
    }


//    业务 =============


    /**
     * 获取指定sftp服务器上 指定目录下 指定文件名(含后缀) 的文本内容
     *
     * @param sftp     sftp
     * @param filePath 文件目录
     * @param fileName 文件名称
     * @return
     */
    public static String getTextFileContent(ChannelSftp sftp, String filePath, String fileName) {
        // 目录 及 文件名称
        String path = filePath + fileName;
        log.error("getTextFileContent. path:{}", path);

        //限制文件类型
        List<String> fileTypeStrList = Lists.newArrayList("txt", "html");
        String[] split = fileName.split("\\.");
        String fileTypeStr = split[split.length - 1];
        if (!fileTypeStrList.contains(fileTypeStr)) {
            log.error("getTextFileContent fileTypeStr is not contains. path:{}", path);
            return StringUtils.EMPTY;
        }

        StringBuilder stringBuilder = new StringBuilder();
        try {
            // 判断查看目录是否存在
            if (!isDirExist(sftp, filePath)) {
                log.error("getTextFileContent filePath isDirExist is false. path:{}", path);
                return StringUtils.EMPTY;
            }
            // 获取input stream
            InputStream inputStream = sftp.get(path);
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
            String line;
            BufferedReader br = new BufferedReader(inputStreamReader);
            while ((line = br.readLine()) != null) {
                stringBuilder.append(line);
            }
        } catch (SftpException | IOException e) {
            log.error("getTextFileContent. e:{}", e.toString());
            e.printStackTrace();
        }
        return stringBuilder.toString();
    }


    /**
     * 判断文件路径在sftp服务器是否存在
     *
     * @param sftp          sftp
     * @param directoryPath 文件夹路径 如: roster/test.html
     * @return
     */
    public static boolean isDirExist(ChannelSftp sftp, String directoryPath) {
        if (StringUtils.isEmpty(directoryPath)) {
            log.error("isDirExist directoryPath is empty.");
            return false;
        }
        try {
            // 判断文件在sftp服务器是否存在
            SftpATTRS lstat = sftp.lstat(directoryPath);
            System.out.println("is Dir:" + lstat.isDir() + "====:" + directoryPath);
            if (lstat.isDir()) {
                return true;
            }
        } catch (SftpException e) {
            log.error("isDirExist error. e:{}", e.toString());
            e.printStackTrace();
        }
        return false;
    }


    /**
     * 创建一个文件夹
     *
     * @param sftp       sftp
     * @param createPath 创建目录(以 / 结尾)
     * @return
     */
    public static boolean createDir(ChannelSftp sftp, String createPath) {
        // 创建目录不为空
        if (StringUtils.isEmpty(createPath)) {
            log.error("createDir createPath is empty.");
            return false;
        }
        // 创建目录以 / 结尾
        boolean endsWith = createPath.endsWith("/");
        if (!endsWith) {
            log.error("createDir createPath endsWith is not 【/】.");
            return false;
        }
        // 如果已经存在此目录则直接返回成功
        if (isDirExist(sftp, createPath)) {
            log.error("createDir createPath isDirExist is true.");
            return true;
        }
        // 创建目录 mkdir
        try {
            String[] split = createPath.split("/");
            StringBuilder sb = new StringBuilder();
            for (String path : split) {
                sb.append(path).append("/");
                String sbPath = sb.toString();
                if (!isDirExist(sftp, sbPath)) {
                    sftp.mkdir(sbPath);
                }
            }
            return true;
        } catch (SftpException e) {
            log.error("createDir mkdir error. e:{}", e.toString());
            e.printStackTrace();
        }
        return false;
    }


    /**
     * 删除一个文件夹
     *
     * @param sftp       sftp
     * @param deletePath 删除目录(以 / 结尾)
     * @return
     */
    public static boolean deleteDir(ChannelSftp sftp, String deletePath) {
        // 删除目录不为空
        if (StringUtils.isEmpty(deletePath)) {
            log.error("deleteDir deletePath is empty.");
            return false;
        }
        // 删除目录以 / 结尾
        boolean endsWith = deletePath.endsWith("/");
        if (!endsWith) {
            log.error("deleteDir deletePath endsWith is not 【/】.");
            return false;
        }
        // 如果不存在此目录则直接返回成功
        if (!isDirExist(sftp, deletePath)) {
            log.error("deleteDir deletePath isDirExist is false.");
            return true;
        }
        // 删除
        try {
            sftp.rmdir(deletePath);
            return true;
        } catch (SftpException e) {
            log.error("deleteDir rm error. e:{}", e.toString());
            e.printStackTrace();
        }
        return false;
    }


    /**
     * 删除文件
     *
     * @param sftp     sftp
     * @param filePath /roster
     * @param fileName /test.html
     * @return
     */
    public static boolean deleteFile(ChannelSftp sftp, String filePath, String fileName) {
        // 参数校验
        if (StringUtils.isEmpty(filePath) || StringUtils.isEmpty(fileName)) {
            log.error("deleteFile path is empty. filePath:{}, filePath:{}", filePath, fileName);
            return false;
        }
        // 目录 及 文件名称
        String path = filePath + fileName;
        log.error("deleteFile path:{}", path);

        // 判断目录是否存在
        if (!isDirExist(sftp, filePath)) {
            log.error("deleteFile filePath isDirExist is false. path:{}", path);
            return false;
        }

        // 删除
        try {
            sftp.rm(path);
            return true;
        } catch (SftpException e) {
            log.error("deleteFile rm error. e:{}", e.toString());
            e.printStackTrace();
        }
        return false;
    }


    /**
     * 文件上传
     *
     * @param sftp           sftp
     * @param fileStream     文件输入流
     * @param uploadFilePath 上传文件夹路径
     * @param uploadFileName 上传文件名称
     * @return
     */
    public static boolean uploadFile(ChannelSftp sftp, InputStream fileStream, String uploadFilePath, String uploadFileName) {
        // 参数校验
        if (Objects.isNull(fileStream) || StringUtils.isEmpty(uploadFilePath) || StringUtils.isEmpty(uploadFileName)) {
            log.error("uploadFile data is empty. fileStream:{}, uploadFilePath:{}, uploadFileName:{}", fileStream, uploadFilePath, uploadFileName);
            return false;
        }

        // 目录 及 文件名称
        String path = uploadFilePath + uploadFileName;
        log.error("uploadFile uploadFilePath:{}", path);

        // 判断上传目录是否存在
        if (!isDirExist(sftp, uploadFilePath)) {
            log.error("uploadFile uploadFilePath isDirExist is false. path:{}", path);
            return false;
        }

        // 上传
        try {
            sftp.put(fileStream, path);
            return true;
        } catch (SftpException e) {
            log.error("uploadFile put error. e:{}", e.toString());
            e.printStackTrace();
        }

        return false;
    }


}

四、测试功能

登录sftp服务器

我们使用xshell登录仅sftp服务器

进入到roster目录下

目前只有roster目录,crisis/notification/email/ 这三层文件夹目录均不存在。

测试创建文件夹

我们执行创建文件夹【roster/crisis/notification/email/】

// 创建文件夹
boolean dir = SftpUtils.createDir(sftp, "roster/crisis/notification/email/");

我们可以看到 依层级关系将目录结构文件夹均创建好了

测试文件上传

我们本地有一个1.html文件 我们试着将其上传到 sftp服务器 刚刚创建的目录上去

// 上传一个文件
File file = new File("C:\\Users\\Administrator\\Desktop\\邮件模板\\1.html");
FileInputStream fileInputStream = new FileInputStream(file);
boolean uploadFile = SftpUtils.uploadFile(sftp, fileInputStream, "roster/crisis/notification/email/", file.getName());

执行成功后,可以看到1.html 文件被成功上传到了sftp服务器的roster/crisis/notification/email/目录下

测试文件读取

我们执行如下读取

// 获取指定file文本
String fileContent = SftpUtils.getTextFileContent(sftp, "roster/crisis/notification/email/", "1.html");
System.out.println(fileContent);

查看控制台,打印1.html 内容如下

相关推荐

  1. Linux Crontab定时表教学大全(!)

    2024-04-01 12:30:02       21 阅读
  2. SFTP服务详解:安全高效的文件传输新选择

    2024-04-01 12:30:02       13 阅读
  3. sftp上传下载文件

    2024-04-01 12:30:02       41 阅读
  4. 【Linux】SFTP定时下载文件

    2024-04-01 12:30:02       16 阅读

最近更新

  1. 怎么把数据转换成百度k线图

    2024-04-01 12:30:02       0 阅读
  2. 什么是软件定义安全SDSec

    2024-04-01 12:30:02       0 阅读
  3. [数仓]十、离线数仓(安全集群实战)

    2024-04-01 12:30:02       0 阅读
  4. pycharm中快捷键汇总

    2024-04-01 12:30:02       1 阅读
  5. Python爬虫原理以及3个小案例(源码)

    2024-04-01 12:30:02       1 阅读
  6. PySpark 中 RDD 与 DataFrame 的不同应用场景

    2024-04-01 12:30:02       1 阅读

热门阅读

  1. 第7周 Python函数刷题(二)

    2024-04-01 12:30:02       14 阅读
  2. Oracle用户密码过期及修改密码有效期

    2024-04-01 12:30:02       15 阅读
  3. 华为鲲鹏认证考试内容有哪些

    2024-04-01 12:30:02       23 阅读
  4. C++经典面试题目(十六)

    2024-04-01 12:30:02       18 阅读
  5. go语言 私用仓库包下载

    2024-04-01 12:30:02       22 阅读
  6. 旋转矩阵与旋转向量

    2024-04-01 12:30:02       21 阅读
  7. Nacos 实现服务平滑上下线(Ribbon 和 LB)

    2024-04-01 12:30:02       19 阅读
  8. 2024.2.10力扣每日一题——二叉树的中序遍历

    2024-04-01 12:30:02       21 阅读