You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用JSch在Java中获取SFTP服务器目录完整层级结构

我来帮你把这段代码完善成能递归遍历SFTP远程目录完整层级的版本~

用JSch递归遍历SFTP远程目录的完整层级结构

你目前的代码只实现了单层目录的遍历,要获取包含子文件夹的完整层级结构,核心是递归处理每个子目录。下面是完善后的完整代码示例:

import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.ChannelSftp.LsEntry;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

public class SftpDirTraversal {

    public static void main(String[] args) {
        // 替换成你的SFTP服务信息
        String host = "your-sftp-host";
        int port = 22;
        String username = "your-username";
        String password = "your-password";
        String remoteRootDir = "/your/target/directory";

        Session session = null;
        ChannelSftp sftpChannel = null;

        try {
            // 初始化JSch并建立Session
            JSch jsch = new JSch();
            session = jsch.getSession(username, host, port);
            session.setPassword(password);
            // 跳过主机密钥验证(生产环境不建议,最好配置信任密钥)
            session.setConfig("StrictHostKeyChecking", "no");
            session.connect();

            // 打开SFTP通道
            sftpChannel = (ChannelSftp) session.openChannel("sftp");
            sftpChannel.connect();

            // 存储完整目录结构的列表
            List<String> fullDirStructure = new ArrayList<>();
            // 启动递归遍历
            traverseRemoteDir(sftpChannel, remoteRootDir, fullDirStructure);

            // 打印结果
            System.out.println("远程目录完整层级:");
            for (String path : fullDirStructure) {
                System.out.println(path);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 确保资源正确关闭
            if (sftpChannel != null && sftpChannel.isConnected()) {
                sftpChannel.disconnect();
            }
            if (session != null && session.isConnected()) {
                session.disconnect();
            }
        }
    }

    /**
     * 递归遍历SFTP目录,收集所有文件和文件夹的完整路径
     * @param sftpChannel 已连接的SFTP通道
     * @param currentDir 当前遍历的目录路径
     * @param resultList 存储结果的列表
     */
    private static void traverseRemoteDir(ChannelSftp sftpChannel, String currentDir, List<String> resultList) throws Exception {
        // 切换到当前目录
        sftpChannel.cd(currentDir);
        // 获取当前目录下的所有条目
        Vector<?> entries = sftpChannel.ls("*");

        for (Object entryObj : entries) {
            if (entryObj instanceof LsEntry) {
                LsEntry entry = (LsEntry) entryObj;
                String entryName = entry.getFilename();

                // 跳过.和..目录,避免无限递归
                if (entryName.equals(".") || entryName.equals("..")) {
                    continue;
                }

                // 拼接完整路径
                String fullPath = currentDir + "/" + entryName;
                // 将路径加入结果列表
                resultList.add(fullPath);

                // 如果是目录,递归遍历其子内容
                if (entry.getAttrs().isDir()) {
                    traverseRemoteDir(sftpChannel, fullPath, resultList);
                }
            }
        }
    }
}

几个关键细节说明:

  • 递归核心:traverseRemoteDir方法会判断每个条目是否是目录,如果是就递归调用自身,深入遍历子目录,这样就能覆盖所有层级。
  • 避免无限递归:必须跳过.和..这两个特殊目录,不然会一直循环遍历上级目录。
  • 资源安全:在finally块里手动关闭SFTP通道和Session,防止资源泄漏。
  • 生产环境优化:代码里的StrictHostKeyChecking=no是为了方便测试,生产环境建议配置信任的主机密钥,或者用密钥登录替代密码登录,提升安全性。

如果需要区分每个条目是文件还是目录,可以把结果列表改成存储自定义实体类,比如:

public class SftpItem {
    private String fullPath;
    private boolean isDirectory;

    // 构造方法、getter、setter
}

遍历的时候创建SftpItem对象加入列表,就能更清晰地区分每个条目的类型啦~

内容的提问来源于stack exchange,提问作者Ayush

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 07:44:41