SftpInboundGateway/Adapter本地有副本时是否不重拉远程文件及方案咨询
关于SftpInboundAdapter拉取逻辑与需求实现的解答
问题1:观察到的现象是否正确?
该现象完全符合SftpInboundAdapter的默认运行逻辑,核心原因有两点:
- 默认开启本地文件存在性校验:适配器会优先检查本地目标目录下是否存在与远程文件同名的文件,存在则直接判定文件已拉取,不会发起SFTP连接请求远程文件
- 默认加载
AcceptOnceFileListFilter过滤器:该过滤器会持久化记录已处理过的远程文件元数据(文件名、大小、修改时间等),哪怕本地文件被重命名,只要远程文件的元数据未触发过滤阈值,适配器依然会跳过拉取操作
关于setLocalFilenameExpression(...)的额外作用:
该方法除调整本地文件名格式外,还有三个核心作用:
- 绕过默认同名本地文件校验:如果表达式中加入动态变量(时间戳、UUID、业务标识等),本地存储的文件名不会重复,默认的本地存在性校验会直接失效,适配器每次轮询都会主动检查远程文件更新状态
- 内置归档逻辑:拉取阶段就可以直接生成符合业务要求的归档文件名,不需要额外编写文件重命名的后置处理逻辑,减少IO操作
- 规避多实例部署冲突:多节点部署时可以在文件名中加入实例标识,避免不同节点拉取同一文件时出现本地文件锁冲突
问题2:每月拉取同名远程文件、留存带时间戳副本的实现方案
不需要编写复杂自定义逻辑,按以下步骤调整适配器配置即可:
- 通过
setLocalFilenameExpression直接生成带时间戳的归档文件名,避免本地文件重名
Java配置示例:// 最终生成文件名格式:原文件名_拉取时间戳.后缀,例如 report_20240601103000.xlsx sftpInboundAdapter.setLocalFilenameExpression( "payload.getName().replaceFirst('(\\\\.[^.]+)$', '_' + T(java.time.LocalDateTime).now().format(T(java.time.format.DateTimeFormatter).ofPattern('yyyyMMddHHmmss')) + '$1')" ); - 替换默认过滤器,只拉取当月更新的同名文件,关闭已处理文件拦截逻辑
配置示例:// 1. 配置文件名匹配规则,只拉取目标固定名称的文件 SftpSimplePatternFileListFilter nameFilter = new SftpSimplePatternFileListFilter("你的目标固定文件名"); // 2. 配置时间过滤规则,仅接受最近31天内修改过的文件(适配月度更新场景) SftpLastModifiedFileListFilter timeFilter = new SftpLastModifiedFileListFilter(2678400000L); // 3. 组合过滤器 sftpInboundAdapter.setFilter(new CompositeFileListFilter<>(Arrays.asList(nameFilter, timeFilter))); // 4. 关闭默认本地文件存在性拦截逻辑 sftpInboundAdapter.setLocalFilter(new AcceptAllFileListFilter<>()); - 可选调整:如果需要强制每月拉取一次,不管远程文件修改时间是否更新,可以自定义基于月份判断的过滤器替换上述
SftpLastModifiedFileListFilter即可。
配置完成后,拉取的本地文件会自动带时间戳永久留存,不会影响下月同名远程文件的拉取流程。
内容的提问来源于stack exchange,提问作者JBStonehenge
相关产品推荐
相关产品推荐

