我们在开发中,有时候需要操作服务器上的文件,Spring Boot可以使用JSch库来连接SFTP并进行操作服务器上的文件读写。

创建一个SFTP连接需要以下步骤:

  • 1.创建JSch对象
  • 2.使用JSch对象创建Session对象
  • 3.使用Session对象连接到SFTP服务器
  • 4.打开SFTP通道
  • 5.使用SFTP通道打开SFTP连接
1.添加依赖

pom.xml文件中添加以下依赖:

<dependency>
    <groupId>com.jcraft</groupId>
    <artifactId>jsch</artifactId>
    <version>0.1.55</version>
</dependency>
2.创建SftpConfig配置类
import lombok.Getter;
import lombok.Setter;

/**
 * <p>
 * SFTP连接参数配置类
 * description: 如果后续只需要操作一台固定不变的服务器,可以从配置文件中读取
 * </p>
 *
 * @author snogzixian
 * @Url 宋子宪博客 www.songzixian.com
 * @since 2023-03-13
 */
@Setter
@Getter
public class SftpConfig {
    /**
     * SFTP服务器地址
     */
    private String host;
    /**
     * SFTP服务器端口
     */
    private int port;
    /**
     * SFTP服务器用户名
     */
    private String username;
    /**
     * SFTP服务器密码 如果不使用密码方式则留空
     */
    private String password;
    /**
     * 密钥文件路径,如果不使用密钥连接则留空
     */
    private String privateKeyPath;

    /**
     * 密钥文件口令,如果不使用密钥连接则留空
     */
    private String passphrase;
    /**
     * 连接SFTP服务器超时时间 2秒
     */
    private Integer sessionConnectTimeoutTime = 2000;
    /**
     * 打开通道超时时间 2秒
     */
    private Integer channelSftpConnectTimeoutTime = 2000;

    /**
     * 密码方式连接方法
     *
     * @param host           SFTP服务器地址
     * @param port           SFTP服务器端口
     * @param username       SFTP服务器用户名
     * @param password       SFTP服务器密码 如果不使用连接则留空
     */
    public SftpConfig(String host, int port, String username, String password) {
        this.host = host;
        this.port = port;
        this.username = username;
        this.password = password;
    }

    /**
     * 秘钥方式连接方法
     *
     * @param host           SFTP服务器地址
     * @param port           SFTP服务器端口
     * @param username       SFTP服务器用户名
     * @param privateKeyPath 密钥文件路径,如果不使用密钥连接则留空
     * @param passphrase     密钥文件口令,如果不使用密钥连接则留空
     */
    public SftpConfig(String host, int port, String username,String privateKeyPath, String passphrase) {
        this.host = host;
        this.port = port;
        this.username = username;
        this.privateKeyPath = privateKeyPath;
        this.passphrase = passphrase;
    }

}
3.创建SFTP操作工具类
import com.jcraft.jsch.*;
import com.risk.riskControl.config.SftpConfig;

import java.io.*;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * SFTP操作工具类
 * </p>
 *
 * @author snogzixian
 * @Url 宋子宪博客 www.songzixian.com
 * @since 2023-03-13
 */
public class SftpService {
    /**
     * SFTP连接参数
     */
    private SftpConfig config;
    /**
     * JSch对象,用于创建SFTP连接
     */
    private JSch jsch;
    /**
     * Session对象,用于连接到SFTP服务器
     */
    private Session session;
    /**
     * SFTP通道,用于打开SFTP连接
     */
    private ChannelSftp channelSftp;

    /**
     * 构造函数,初始化SFTP连接参数
     *
     * @param config SFTP连接参数
     */
    public SftpService(SftpConfig config) {
        this.config = config;
        // 创建JSch对象
        this.jsch = new JSch();
    }

    /**
     * 连接到SFTP服务器
     *
     * @throws JSchException
     */
    public void connect() throws JSchException {
        try {
            // 创建Session对象
            session = jsch.getSession(config.getUsername(), config.getHost(), config.getPort());
            if (config.getPassword() != null) {
                // 使用密码连接
                session.setPassword(config.getPassword());
            } else if (config.getPrivateKeyPath() != null) {
                // 使用私钥连接
                jsch.addIdentity(config.getPrivateKeyPath(), config.getPassphrase());
            }
            // 不进行主机密钥检查
            session.setConfig("StrictHostKeyChecking", "no");
            // 设置SFTP连接超时时间
            session.connect(config.getSessionConnectTimeoutTime());
            // 打开SFTP通道
            channelSftp = (ChannelSftp) session.openChannel("sftp");
            // 设置通道连接超时时间
            channelSftp.connect(config.getChannelSftpConnectTimeoutTime());
        } catch (JSchException e) {
            // 连接异常处理
            throw new JSchException("Failed to connect to SFTP server: " + e.getMessage());
        }
    }


    /**
     * 断开SFTP连接
     */
    public void disconnect() {
        if (channelSftp != null) {
            // 断开SFTP连接
            channelSftp.disconnect();
        }
        if (session != null) {
            // 断开Session连接
            session.disconnect();
        }
    }

    /**
     * 上传文件到SFTP服务器
     *
     * @param localFilePath  本地文件路径
     * @param remoteFilePath SFTP服务器文件路径
     * @throws SftpException
     * @throws FileNotFoundException
     */
    public void uploadFile(String localFilePath, String remoteFilePath) throws SftpException, IOException {
        // 使用try-with-resources语句,可以自动关闭资源
        try (InputStream inputStream = new FileInputStream(localFilePath)) {
            // 上传文件到SFTP服务器
            channelSftp.put(inputStream, remoteFilePath);
        }
    }

    /**
     * 从SFTP服务器下载文件
     *
     * @param remoteFilePath SFTP服务器文件路径
     * @param localFilePath  本地文件路径
     * @throws SftpException
     * @throws FileNotFoundException
     */
    public void downloadFile(String remoteFilePath, String localFilePath) throws SftpException, IOException {
        // 使用try-with-resources语句,可以自动关闭资源
        try (OutputStream outputStream = new FileOutputStream(localFilePath)) {
            // 从SFTP服务器下载文件
            channelSftp.get(remoteFilePath, outputStream);
        }
    }

    /**
     * 删除SFTP服务器上的文件
     *
     * @param remoteFilePath SFTP服务器文件路径
     * @throws SftpException
     */
    public void deleteFile(String remoteFilePath) throws SftpException {
        // 删除SFTP服务器上的文件
        channelSftp.rm(remoteFilePath);
    }

    /**
     * 列出SFTP服务器上的文件
     * 使用这段代码会有什么问题,是否还可以优化
     *
     * @param remoteDirectory SFTP服务器目录
     * @return 文件列表
     * @throws SftpException
     */
    public List<String> listFiles(String remoteDirectory) throws SftpException {
        List<String> fileList;
        // 列出SFTP服务器上的文件
        try (Stream<ChannelSftp.LsEntry> stream = channelSftp.ls(remoteDirectory).stream()) {
            fileList = stream
                    // 过滤掉目录
                    .filter(entry -> !entry.getAttrs().isDir())
                    // 获取文件名
                    .map(ChannelSftp.LsEntry::getFilename)
                    // 将文件名收集到List中
                    .collect(Collectors.toList());
        }
        return fileList;
    }

}
4.创建SftpTest测试类
import com.risk.riskControl.config.SftpConfig;

import java.util.List;

/**
 * /**
 * <p>
 * SftpTest测试类
 * </p>
 *
 * @author snogzixian
 * @Url 宋子宪博客 www.songzixian.com
 * @since 2023-03-13
 */
public class SftpTest {

    /**
     * 测试SFTP连接及文件上传、下载、删除、列出操作
     *
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        // 构建SFTP参数,如果是参数固定一个不变改为用配置文件读取
        SftpConfig config = new SftpConfig("sftp.songzixian.com", 22, "szxBlog", "12345678");
        // 秘钥方式连接
        //SftpConfig config = new SftpConfig("sftp.songzixian.com", 22, "root", "D:\\id_rsa_szx_blog.ppk","blog123");
        // 连接到SFTP服务器
        SftpService sftpService = new SftpService(config);
        sftpService.connect();
        // 本地路径
        String localFilePath = "";
        // 服务器路径
        String remoteFilePath = "";
        // 上传文件使用
        // 本地文件路径
        localFilePath = "D:\\code\\a.txt";
        // SFTP服务器文件路径
        remoteFilePath = "/usr/local/sftp-test/a.txt";
        // 上传文件到SFTP服务器
        sftpService.uploadFile(localFilePath, remoteFilePath);

        // 下载文件使用
        // SFTP服务器文件路径
        remoteFilePath = "/usr/local/sftp-test/a.txt";
        // 本地文件路径
        localFilePath = "D:\\code\\aaaa.txt";
        // 从SFTP服务器下载文件
        sftpService.downloadFile(remoteFilePath, localFilePath);
        // 删除文件使用
        remoteFilePath = "/usr/local/sftp-test/a.txt";
        // 删除SFTP服务器上的文件
        sftpService.deleteFile(remoteFilePath);

        // 列出文件
        // SFTP服务器目录
        String remoteDirectory = "/usr/local/sftp-test/";
        // 列出SFTP服务器上的文件
        List<String> files = sftpService.listFiles(remoteDirectory);
        for (String file : files) {
            System.out.println(file);
        }

        System.out.println("操作成功");
        // 断开SFTP连接
        sftpService.disconnect();
    }

}
Last modification:March 15, 2023
如果觉得这篇技术文章对你有用,请随意赞赏