如何通过Spring Integration SMB入站适配器丢弃过期远程文件
问题
我的应用需要定期从远程文件服务器下载文件,基于Spring Integration SMB的实现可正常运行(代码如下)。但受基础架构和运行时条件限制,应用无法控制远程服务器及本地目录的文件删除时机,可能导致文件重复下载,浪费网络与存储资源。
短期可通过AcceptOnceFileListFilter解决该问题,但出于技术简洁性考虑,我不想使用元数据存储,因此该过滤器无法在系统重启后保留状态,长期存在隐患。
我的业务场景允许仅轮询未达到指定时长(如数天)的远程文件(基于最后修改时间),即需要类似反向的SmbLastModifiedFileListFilter(该过滤器会丢弃过新的文件)。是否有简单的实现方式?若能结合现有SmbLastModifiedFileListFilter实现时间区间过滤则更佳。
@Bean public IntegrationFlow integrationFlow() { return IntegrationFlow.from( Smb.inboundAdapter(smbSessionFactory()) .remoteDirectory("/myRemoteDirectory") .filter(fileListFilter()) .localDirectory(new File("/myLocalDirectory")) .autoCreateLocalDirectory(true) .preserveTimestamp(true), e -> e.poller(Pollers.fixedDelay(60000).maxMessagesPerPoll(-1)) ) .channel(new NullChannel()) // Discard payload .get(); } @Bean public CompositeFileListFilter<SmbFile> fileListFilter() { final var filters = new CompositeFileListFilter<SmbFile>(); filters.addFilter(new AcceptOnceFileListFilter<>()); filters.addFilter(new SmbRegexPatternFileListFilter(".*\\.txt")); filters.addFilter(new SmbLastModifiedFileListFilter(30)); // another "reverse" SmbLastModifiedFileListFilter required here return filters; }
解决方案
方式一:自定义反向的SmbLastModifiedFileListFilter
直接继承AbstractLastModifiedFileListFilter<SmbFile>,重写accept方法,保留最后修改时间距今不超过指定时长的文件(与原过滤器逻辑完全相反):
public class SmbNewerThanLastModifiedFileListFilter extends AbstractLastModifiedFileListFilter<SmbFile> { public SmbNewerThanLastModifiedFileListFilter(long age) { super(age); } @Override protected long getLastModified(SmbFile file) { return file.getLastModified(); } @Override public boolean accept(SmbFile file) { long cutoff = System.currentTimeMillis() - this.getAge(); // 仅保留最后修改时间晚于cutoff的文件(即文件未超过指定时长) return file.getLastModified() >= cutoff; } }
方式二:组合过滤器实现时间区间过滤
如果需要同时过滤出**最后修改时间在[X天前, Y分钟内]**的文件,直接组合原SmbLastModifiedFileListFilter和自定义过滤器即可,既避免下载过旧文件,也避免下载未完全写入的新文件:
@Bean public CompositeFileListFilter<SmbFile> fileListFilter() { final var filters = new CompositeFileListFilter<SmbFile>(); filters.addFilter(new SmbRegexPatternFileListFilter(".*\\.txt")); // 保留最后修改时间不超过7天的文件(换算为毫秒:7*24*60*60*1000=604800000) filters.addFilter(new SmbNewerThanLastModifiedFileListFilter(604800000)); // 保留最后修改时间超过30分钟的文件,避免下载未写完的文件 filters.addFilter(new SmbLastModifiedFileListFilter(30)); return filters; }
关键说明
- 自定义过滤器完全基于文件本身的最后修改时间判断,无需依赖任何元数据存储,重启后状态不受影响,符合技术简洁性要求。
- 可以直接去掉原
AcceptOnceFileListFilter,因为时间过滤逻辑已经能避免重复下载(只要远程文件的最后修改时间不被篡改)。
内容的提问来源于stack exchange,提问作者mrnst
相关产品推荐
相关产品推荐

