如何使用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
相关产品推荐
相关产品推荐

