
本文详解如何在 apache camel 中通过 delete 或 move 参数控制 sftp 下载后源文件的处理行为,避免重复拉取、文件残留等问题,并提供可立即使用的路由配置与最佳实践。
本文详解如何在 apache camel 中通过 delete 或 move 参数控制 sftp 下载后源文件的处理行为,避免重复拉取、文件残留等问题,并提供可立即使用的路由配置与最佳实践。
在使用 Apache Camel 的 camel-ftp 组件(含 SFTP 支持)实现文件下载时,一个常见误区是认为 .to("file://...") 会自动将远程文件“移动”或“移除”。实际上,Camel 默认仅执行下载(copy),绝不会修改远程服务器上的原始文件——该文件将始终保留在 SFTP 服务器上,导致后续轮询或重复调用时持续被再次消费,引发重复处理、磁盘占用或业务逻辑异常。
要解决此问题,必须显式配置文件消费后的后置动作。Camel 提供了两个核心参数:
- delete=true:下载成功后立即删除远程文件(不可逆,适用于一次性任务);
- move=xxx:下载成功后将远程文件重命名或移动到指定子路径(推荐用于需审计留痕或失败回溯的场景)。
✅ 正确配置示例(推荐 move 方案):
from("sftp://server/?username=user&password=pass&passiveMode=true" +
"&disconnect=true" +
"&move=.processed/${file:name}" + // 下载后将原文件移至 .processed/ 目录并保留原名
"&readLock=changed&readLockCheckInterval=5000") // 防止读取中文件被覆盖
.routeId("SFTP_File_Route")
.log("Downloading file: ${file:name}")
.to("file://C:/myLocal?fileName=${file:name}")
.log("File ${file:name} downloaded and remote moved to .processed/");⚠️ 关键注意事项:
- move 路径为远程 SFTP 服务器上的相对路径(如 .processed/),需确保目标目录存在或具备创建权限;
- delete=true 无回退机制,生产环境建议优先使用 move 并配合监控告警;
- 原代码中每次 API 调用都 addRoutes() 会导致路由重复注册、资源泄漏。应改为:
✅ 启动时静态加载路由(如 @Component + RouteBuilder),
✅ 或使用 ProducerTemplate 触发单次下载(更轻量、可控); - 添加 readLock=changed 可规避文件写入未完成即开始下载的风险;
- disconnect=true 已启用,确保连接及时释放,但不解决文件残留问题。
? 总结:SFTP 下载的本质是“复制”,而非“移动”。Camel 不会擅自删除或移动远程文件,一切需由开发者通过 delete / move 显式声明意图。结合幂等性设计(如文件名哈希去重)、异常兜底(如 onException 中恢复 move 状态)及日志追踪,才能构建健壮的文件集成流程。










