SFTP 远程文件操作学习实践(一)

142 阅读2分钟

我需要的是一个远程文件检测的工具类。需求是从程序运行主机上去访问另一台主机的特定文件目录,检测是否有指定命名格式的文件(特定文件即是否入库)。 实现代码如下:

import com.jcraft.jsch.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Properties;
import java.util.Vector;

/**
 * 用于与远程服务器进行文件操作,包括检查文件是否存在和列出远程目录下的所有文件。
 */
@Slf4j
@Component
public class RemoteFileUtil {

    @Value("${sftp.host}")
    private String host;

    @Value("${sftp.port}")
    private int port;

    @Value("${sftp.username}")
    private String username;

    @Value("${sftp.password}")
    private String password;

    private Session getSession() throws JSchException {
        JSch jsch = new JSch();
        Session session = jsch.getSession(username, host, port);
        session.setPassword(password);

        Properties config = new Properties();
        config.put("StrictHostKeyChecking", "no");
        session.setConfig(config);

        return session;
    }

    /**
     * 检查远程文件是否存在
     * @param remotePath 远程目录路径
     * @param fileName 文件名
     * @return 文件是否存在
     */
    public boolean checkFileExists(String remotePath, String fileName) {
        Session session = null;
        ChannelSftp channelSftp = null;

        try {
            session = getSession();
            session.connect(30000); // 设置超时时间30秒

            channelSftp = (ChannelSftp) session.openChannel("sftp");
            channelSftp.connect();

            // 切换到目标目录
            channelSftp.cd(remotePath);

            // 获取文件列表
            Vector<ChannelSftp.LsEntry> fileList = channelSftp.ls("*");

            // 检查文件是否存在
            return fileList.stream()
                    .map(ChannelSftp.LsEntry::getFilename)
                    .anyMatch(name -> name.equals(fileName));

        } catch (Exception e) {
            log.error("检查远程文件失败: {}", e.getMessage(), e);
            return false;
        } finally {
            closeConnection(channelSftp, session);
        }
    }

    /**
     * 获取远程目录下的所有文件
     * @param remotePath 远程目录路径
     * @return 文件名列表
     */
    public Vector<ChannelSftp.LsEntry> listFiles(String remotePath) {
        Session session = null;
        ChannelSftp channelSftp = null;

        try {
            session = getSession();
            session.connect(30000);

            channelSftp = (ChannelSftp) session.openChannel("sftp");
            channelSftp.connect();

            channelSftp.cd(remotePath);
            return channelSftp.ls("*");

        } catch (Exception e) {
            log.error("获取远程文件列表失败: {}", e.getMessage(), e);
            return null;
        } finally {
            closeConnection(channelSftp, session);
        }
    }

    /**
     * 关闭连接
     */
    private void closeConnection(ChannelSftp channelSftp, Session session) {
        if (channelSftp != null && channelSftp.isConnected()) {
            channelSftp.disconnect();
        }
        if (session != null && session.isConnected()) {
            session.disconnect();
        }
    }
}

在配置文件中配置好

sftp.host= #访问主机地址
sftp.port=22 #访问端口号
sftp.username=june #访问用户名
sftp.password= #访问用户密码 
sftp.timeout=30000 #设置连接超时时间

在这块代码中仅实现了文件检测、读取目录下所有文件的功能。文件下载、文件上传功能以后有机会在去实现。 通过这个需求学习了SFTP协议,基于SSH的文件传输协议。了解了服务器上搭建SFTP服务器的流程。 在这个程序运行中,要特别注意的是权限问题。

代码有值得改进的地方,比如我认为建立sftp连接的代码可以抽取出来进行单独处理。文件上传、下载后续深入学习在研究。