SpringBoot连接Sftp服务器实现文件上传/下载(亲测可用)

目录

一、先导入pom依赖

二、工具类完整代码


一、先导入pom依赖

XML 复制代码
<dependency>
    <groupId>com.jcraft</groupId>
    <artifactId>jsch</artifactId>
    <version>0.1.55</version>
</dependency>

二、工具类完整代码

java 复制代码
package com.example.excel.util;

import com.jcraft.jsch.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Properties;
import java.util.Vector;

/**
 * SFTP工具类
 * 功能:测试连接、下载文件、上传文件
 */
public class SftpUtil {
    private static final Logger log = LoggerFactory.getLogger(SftpUtil.class);
    
    private final String host;
    private final int port;
    private final String username;
    private final String password;
    private Session session;
    private ChannelSftp channel;

    public SftpUtil(String host, int port, String username, String password) {
        this.host = host;
        this.port = port;
        this.username = username;
        this.password = password;
    }

    /**
     * 测试SFTP连接
     * @return true连接成功,false连接失败
     */
    public boolean testConnection() {
        try {
            connect();
            return true;
        } catch (JSchException e) {
            log.error("SFTP连接测试失败: {}", e.getMessage());
            return false;
        } finally {
            disconnect();
        }
    }

    /**
     * 下载文件
     * @param remotePath 远程文件路径
     * @param localPath 本地保存路径
     * @return true下载成功,false下载失败
     */
    public boolean downloadFile(String remotePath, String localPath) {
        try (OutputStream output = Files.newOutputStream(Paths.get(localPath))) {
            connect();
            channel.get(remotePath, output);
            log.info("文件下载成功: {} -> {}", remotePath, localPath);
            return true;
        } catch (JSchException | SftpException | IOException e) {
            log.error("文件下载失败: {}", e.getMessage());
            return false;
        } finally {
            disconnect();
        }
    }

    /**
     * 上传文件
     * @param localPath 本地文件路径
     * @param remotePath 远程保存路径
     * @return true上传成功,false上传失败
     */
    public boolean uploadFile(String localPath, String remotePath) {
        try (InputStream input = Files.newInputStream(Paths.get(localPath))) {
            connect();
            // 1. 提取远程目录路径
            String remoteDir = extractDirectoryPath(remotePath);
            // 2. 确保目录存在(不存在则创建)
            ensureDirectoryExists(remoteDir);
            channel.put(input, remotePath);
            log.info("文件上传成功: {} -> {}", localPath, remotePath);
            return true;
        } catch (JSchException | SftpException | IOException e) {
            log.error("文件上传失败: {}", e.getMessage());
            return false;
        } finally {
            disconnect();
        }
    }

    /**
     * 检查远程文件是否存在
     * @param remotePath 远程文件路径
     * @return true存在,false不存在
     */
    public boolean fileExists(String remotePath) {
        try {
            connect();
            channel.lstat(remotePath);
            return true;
        } catch (SftpException e) {
            if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) {
                return false;
            }
            log.error("检查文件存在时出错: {}", e.getMessage());
            return false;
        } catch (JSchException e) {
            log.error("连接异常: {}", e.getMessage());
            return false;
        } finally {
            disconnect();
        }
    }

    /**
     * 创建SFTP连接
     */
    private void connect() throws JSchException {
        if (channel != null && channel.isConnected()) {
            return;
        }

        JSch jsch = new JSch();
        session = jsch.getSession(username, host, port);
        session.setPassword(password);
        
        // 配置不检查主机密钥(生产环境应配置known_hosts)
        Properties config = new Properties();
        config.put("StrictHostKeyChecking", "no");
        session.setConfig(config);
        
        session.connect();
        Channel channel = session.openChannel("sftp");
        channel.connect();
        this.channel = (ChannelSftp) channel;
    }

    /**
     * 从文件路径中提取目录路径
     * @param filePath 完整文件路径
     * @return 目录路径
     */
    private String extractDirectoryPath(String filePath) {
        int lastSlash = filePath.lastIndexOf('/');
        if (lastSlash <= 0) {
            return "/"; // 根目录
        }
        return filePath.substring(0, lastSlash);
    }

    /**
     * 确保远程目录存在(不存在则递归创建)
     * @param remoteDir 远程目录路径
     */
    private void ensureDirectoryExists(String remoteDir) throws SftpException {
        try {
            // 尝试进入目录(存在则直接返回)
            channel.cd(remoteDir);
        } catch (SftpException e) {
            // 目录不存在,需要创建
            if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) {
                // 递归创建父目录
                int lastSlash = remoteDir.lastIndexOf('/');
                if (lastSlash > 0) {
                    String parentDir = remoteDir.substring(0, lastSlash);
                    ensureDirectoryExists(parentDir);
                }

                // 创建当前目录
                channel.mkdir(remoteDir);
                channel.cd(remoteDir); // 进入新创建的目录
                log.debug("创建目录: {}", remoteDir);
            } else {
                throw e; // 其他异常重新抛出
            }
        }
    }

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

    // 使用示例
    public static void main(String[] args) {
        // 1. 创建SFTP工具实例
        SftpUtil sftp = new SftpUtil("10.10.10.10",
                2222,
                "username",
                "password");
        
        // 2. 测试连接
        System.out.println("连接测试: " + (sftp.testConnection() ? "成功" : "失败"));
        
        // 3. 检查文件是否存在
        String remoteFile = "/remote/path/test.txt";
        System.out.println("文件存在检查: " + (sftp.fileExists(remoteFile) ? "存在" : "不存在"));

        // 4. 下载文件
        sftp.downloadFile("/upload/test/test.zip", "D:\\local.zip");

        // 5. 上传文件
        sftp.uploadFile("C:\\Users\\test\\Desktop\\log.log", "/upload/test/test.log");
    }
}
相关推荐
垆边人似月.17 分钟前
RDMA 文件传输踩坑(四):从固定延时改造为 READY/ACK 协议
linux·服务器·网络
服务器硬件项目经理36 分钟前
《超节点修仙录》· 第一卷·炼气期【第04话】 超节点 vs 普通服务器——不就是多插了几张卡吗?
运维·服务器·人工智能·嵌入式硬件·深度学习·机器学习
wflynn1 小时前
GitHub 日榜趋势速报 | 2026-10-30
开源·github
程序猿老A1 小时前
轻量应用服务器怎么搭建 WordPress站点?
服务器
snysy2 小时前
服务器安全加固与入侵检测实战:从SSH加固、防火墙策略到挖矿木马排查
服务器·安全·ssh
CoderYanger2 小时前
Java EE 进阶:5. Spring IoC&DI(第三弹):Spring DI
java·开发语言·spring boot·spring·面试·java-ee·mvc
miofly2 小时前
Anthropic为Claude四款模型加水印,两款旧模型留调参漏洞
开源·github
m4Rk_2 小时前
【论文阅读】Agent 记忆机制(116):Hybrid Memory——用互补策展与离线巩固构建长期记忆
论文阅读·人工智能·学习·开源·github
小此方2 小时前
C++ 工程组件与基础设施(三)详解RPC服务的概念与安装,图片介绍Brpc服务器和客户端的搭建过程
服务器·c++·rpc
老李IT笔记3 小时前
抹除之后机器上的受管应用可以留下:这一步省掉的是哪段时间
运维·服务器