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

如何使用Spring Integration SFTP实现目录及子目录的上传与下载

Spring Boot + Spring Integration SFTP 目录上传/下载实现

一、目录下载(含子目录)

你当前的单文件下载代码只需调整几个关键配置,即可实现远程目录(含子目录)的完整同步:

核心修改点

  • 开启递归同步:给SftpInboundFileSynchronizer设置setRecursive(true),使其遍历远程子目录
  • 调整文件过滤器:默认过滤器会排除目录,需使用CompositeFileListFilter组合目录允许规则和文件过滤规则
  • 保留远程目录结构:通过setLocalFilenameGeneratorExpression让本地自动创建对应子目录

修改后的下载代码

@Bean
public DefaultSftpSessionFactory getSftpSessionFactory() {
    DefaultSftpSessionFactory defaultSftpSessionFactory = new DefaultSftpSessionFactory();
    defaultSftpSessionFactory.setHost("hostName");
    defaultSftpSessionFactory.setPort(22);
    defaultSftpSessionFactory.setAllowUnknownKeys(true);
    defaultSftpSessionFactory.setUser("root");
    defaultSftpSessionFactory.setPassword("12qwaszx");
    return defaultSftpSessionFactory;
}

@Bean(name="mydefaultSync")
public SftpInboundFileSynchronizer synchronizer() {
    SftpInboundFileSynchronizer synchronizer = new SftpInboundFileSynchronizer(getSftpSessionFactory());
    synchronizer.setDeleteRemoteFiles(true);
    synchronizer.setRemoteDirectory("/root/upload/");
    // 开启递归遍历子目录
    synchronizer.setRecursive(true);
    // 组合过滤器:允许所有目录 + 过滤txt文件
    CompositeFileListFilter<ChannelSftp.LsEntry> filter = new CompositeFileListFilter<>();
    filter.addFilter(new SftpSimplePatternFileListFilter("*.txt"));
    filter.addFilter(new AcceptAllFileListFilter<>());
    synchronizer.setFilter(filter);
    // 保留文件时间戳
    synchronizer.setPreserveTimestamp(true);
    return synchronizer;
}

@Bean(name="stfpServer")
@InboundChannelAdapter(channel="fileDownload", poller=@Poller(fixedDelay = "3000"))
public MessageSource<File> sftpMessageSources() {
    SftpInboundFileSynchronizingMessageSource source = new SftpInboundFileSynchronizingMessageSource(synchronizer());
    source.setLocalDirectory(new File("download/"));
    source.setAutoCreateLocalDirectory(true);
    source.setMaxFetchSize(1);
    // 保留远程目录结构,本地自动创建对应子目录
    source.setLocalFilenameGeneratorExpression(new SpelExpressionParser().parseExpression(
            "#remoteDirectory.substring(#remoteDirectory.lastIndexOf('/') + 1) + '/' + #remoteFile.getName()"
    ));
    return source;
}

二、目录上传(含子目录)

要实现本地目录(含子目录)上传到远程SFTP,需要结合FileSplitter递归扫描本地文件,再通过SftpMessageHandler完成上传,并保留目录结构:

上传代码示例

// 递归扫描本地目录的FileSplitter
@Bean
public FileSplitter fileSplitter() {
    return new FileSplitter(true, true); // 第一个true:递归扫描;第二个true:发送目录(可选)
}

// SFTP上传处理器
@Bean
@ServiceActivator(inputChannel = "sftpUploadChannel")
public MessageHandler sftpMessageHandler() {
    SftpMessageHandler handler = new SftpMessageHandler(getSftpSessionFactory());
    // 动态生成远程目录,保留本地子目录结构
    handler.setRemoteDirectoryExpression(new SpelExpressionParser().parseExpression(
            "/root/upload/" + "#file.getParentFile().getName()"
    ));
    handler.setFileNameGenerator(message -> {
        File file = (File) message.getPayload();
        return file.getName();
    });
    handler.setAutoCreateDirectory(true); // 自动创建远程子目录
    return handler;
}

// 触发上传的入口(可通过接口或事件调用)
@Bean
public IntegrationFlow uploadFlow() {
    return IntegrationFlows.from("uploadTriggerChannel")
            .handle(message -> {
                File localDir = new File("local/upload/"); // 本地待上传的目录
                return localDir;
            })
            .split(fileSplitter())
            .channel("sftpUploadChannel")
            .get();
}

使用说明

调用时只需向uploadTriggerChannel发送任意消息,即可触发本地local/upload/目录下所有文件(含子目录)的上传,远程会自动创建对应子目录结构。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 06:50:29