1. 为什么需要SFTP文件夹递归下载与断点续传
在实际开发中,我们经常需要从远程服务器下载文件。SFTP作为SSH协议的一部分,提供了安全的文件传输能力。但原生SFTP客户端有个明显的痛点:它只能单文件操作,无法直接下载整个文件夹。想象一下,如果你要下载一个包含数百个子文件夹和数千个文件的目录结构,手动一个个下载简直是噩梦。
更糟糕的是,当网络不稳定时,下载大文件夹经常会在中途断开。我曾经在一个项目中,花了3小时下载一个20GB的文件夹,结果在95%的时候网络闪断,一切都要从头开始。这种体验实在太糟糕了,于是我决定用Hutool工具库来解决这个问题。
Hutool的Sftp工具类已经封装了基本的SFTP操作,但它的递归下载功能还不够完善。我们需要在它的基础上增加两个关键能力:一是完整的文件夹递归下载,二是可靠的断点续传机制。这样即使在网络不稳定的环境下,也能保证文件传输的可靠性。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与基础配置
2.1 添加必要的依赖
首先,我们需要在项目中引入Hutool和JSch的依赖。JSch是Java实现的SSH2库,Hutool的SFTP功能就是基于它封装的。
如果你使用Maven,在pom.xml中添加:
xml复制<dependencies>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.16</version>
</dependency>
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.54</version>
</dependency>
</dependencies>
如果是Gradle项目,在build.gradle中添加:
groovy复制dependencies {
implementation 'com.jcraft:jsch:0.1.54'
implementation 'cn.hutool:hutool-all:5.8.16'
}
2.2 建立SFTP连接
Hutool提供了非常简便的方式来创建SFTP连接。基本连接代码如下:
java复制import cn.hutool.extra.ssh.JschUtil;
import cn.hutool.extra.ssh.Sftp;
public class SftpDemo {
public static void main(String[] args) {
String host = "your.sftp.server";
int port = 22;
String username = "your_username";
String password = "your_password";
Sftp sftp = JschUtil.createSftp(host, port, username, password);
// 使用完毕后记得关闭连接
sftp.close();
}
}
在实际项目中,我建议把这些连接参数放在配置文件中,而不是硬编码在代码里。这样既安全又便于维护。
3. 实现文件夹递归下载
3.1 基础递归下载实现
Hutool的Sftp类已经提供了基本的文件操作,但没有直接的文件夹递归下载功能。我们需要自己实现这个逻辑。核心思路是:
- 列出远程目录下的所有文件和子目录
- 对于每个文件,直接下载到本地对应路径
- 对于每个子目录,在本地创建对应目录,然后递归处理
下面是实现代码:
java复制import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.ssh.Sftp;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.SftpException;
import java.io.File;
import java.util.Vector;
public class SftpDownloader {
/**
* 递归下载SFTP文件夹
* @param sftp SFTP连接
* @param remotePath 远程路径
* @param localPath 本地路径
* @throws SftpException
*/
public static void downloadDir(Sftp sftp, String remotePath, String localPath) throws SftpException {
ChannelSftp channelSftp = sftp.getClient();
channelSftp.cd(remotePath);
