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

Camel SFTP文件下载问题:文件已复制但路由未关闭重复拉取

解决Camel SFTP路由重复拉取文件的问题

问题描述

搭建了API服务,调用API时通过Camel集成器从外部SFTP服务器下载文件,目前文件已成功复制到本地,但SFTP路由未自动关闭,会持续重复拉取服务器上的文件。

现有代码片段

API代码

@GetMapping("myapicall")
public void fetchFileFromSFTPServer() {
    logger.info("-------Begin of fetchFileFromSFTPServer-------");
    try {
        RouteBuilder routeBuilder = sftpRoute.buildRoute();
        camelContext.addRoutes(routeBuilder);

    } catch (Exception e) {
        logger.error("Error while loading Routes------" + e.getMessage());
    }
    
    camelContext.setUseMDCLogging(true);
    logger.info("-------End of fetchFileFromSFTPServer-------" );
}

路由构建器代码

public RouteBuilder buildRoute() {
    RouteBuilder builder = new RouteBuilder() {

        @Override
        public void configure() throws Exception {
            
            from(
              "sftp://server/?username=**&password=**&passiveMode=true&disconnect=true")
              .routeId("SFTP_File_Route").setExchangePattern(ExchangePattern.InOnly).
              log("connecting to SFTP Server")
              .to("file://C:/myLocal").end();
        }
    };
    return builder;
}

问题根源

Camel的SFTP组件默认采用轮询消费模式,添加路由后会定期检查SFTP服务器并拉取文件,不会自动停止,因此出现重复拉取的情况。

解决方案

方法1:修改SFTP URI参数,实现一次性拉取

在SFTP的URI中添加参数,让路由仅执行一次轮询就停止:

  • 添加 consumer.delay=-1:表示仅轮询一次,完成后停止路由
  • 或组合使用 consumer.maxMessagesPerPoll=1(每次轮询最多拉取1个文件)、stopOnIdleTimeout=true(空闲超时后停止)和 idleTimeout=5000(设置5秒空闲超时)

修改后的SFTP URI示例:

sftp://server/?username=**&password=**&passiveMode=true&disconnect=true&consumer.delay=-1

方法2:手动停止并移除路由

在API中等待文件下载完成后,手动停止并移除对应路由,避免持续轮询。修改后的API代码示例:

@GetMapping("myapicall")
public void fetchFileFromSFTPServer() {
    logger.info("-------Begin of fetchFileFromSFTPServer-------");
    try {
        String routeId = "SFTP_File_Route";
        // 检查路由是否已存在,避免重复添加冲突
        if (!camelContext.getRouteDefinitions().stream().anyMatch(rd -> rd.getId().equals(routeId))) {
            RouteBuilder routeBuilder = sftpRoute.buildRoute();
            camelContext.addRoutes(routeBuilder);
        }
        
        // 等待路由执行完成(实际场景建议用Camel事件监听或异步回调,此处用sleep做简单示例)
        Thread.sleep(3000);
        
        // 停止并移除路由
        if (camelContext.getRouteStatus(routeId).isStarted()) {
            camelContext.stopRoute(routeId);
            camelContext.removeRoute(routeId);
        }
    } catch (Exception e) {
        logger.error("Error while loading Routes------" + e.getMessage());
    }
    
    camelContext.setUseMDCLogging(true);
    logger.info("-------End of fetchFileFromSFTPServer-------" );
}

方法3:使用ProducerTemplate触发一次性传输(推荐)

避免动态添加路由,直接用ProducerTemplate触发一次性文件传输,完成后自动结束,无需持续轮询。示例代码:

@Autowired
private ProducerTemplate producerTemplate;

@GetMapping("myapicall")
public void fetchFileFromSFTPServer() {
    logger.info("-------Begin of fetchFileFromSFTPServer-------");
    try {
        // 直接触发从SFTP到本地的一次性传输
        producerTemplate.send(
            "sftp://server/?username=**&password=**&passiveMode=true",
            exchange -> {
                // 指定要下载的文件名,*表示下载所有文件
                exchange.getIn().setHeader("CamelFileName", "*");
            },
            "file://C:/myLocal"
        );
    } catch (Exception e) {
        logger.error("Error while fetching file------" + e.getMessage());
    }
    logger.info("-------End of fetchFileFromSFTPServer-------" );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 12:57:17