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

如何使用Apache Camel路由将同一份CSV文件保存到两个不同路径?现有路由报错求助

我来帮你解决这个问题——你猜的没错,问题确实出在Exchange的消息体在第一次toD调用后已经被消费掉了,导致后续的to组件找不到要写入的文件内容。下面给你几个可行的解决方案:

方案1:使用Multicast组件并行发送到两个目的地

Multicast可以把同一个Exchange复制多份,分别发送到不同的端点,这样每个端点都能拿到完整的文件内容,是处理这类“一份数据多目的地”场景的最优解之一。

修改后的路由代码:

from("{{csv.generation}}")
    .setHeader("dynamicFileName", constant("Main.csv"))
    // 使用multicast同时分发到两个存储路径
    .multicast()
        .toD("sftp://${properties:ses.sftp.user}@{{ses.sftp.host}}:${properties:${header.country}.sftp.port}${properties:${header.country}.sftp.rdir}?username=${properties:ses.sftp.user}&privateKeyFile={{sftp.prvt.key.path}}&preferredAuthentications=publickey&knownHostsFile={{knownHost.file.path}}&fileName=${header.dynamicFileName}&doneFileName=${header.dynamicFileName}{{cco.files.ready.ext}}")
        // 给第二个路径指定文件名,避免使用默认的Exchange ID作为文件名
        .to("{{save.copy.to.another.path}}?fileName=${header.dynamicFileName}")
    .end()
    .log("target csv file has been saved successfully at ${properties:${header.country}.sftp.rdir} SFTP location")
    .log("Created a copy on Fabric {{save.copy.to.another.path}}${header.dynamicFileName}");

如果需要串行执行(必须等主路径保存成功后再存副本),可以给Multicast加上串行配置:

.multicast().parallelProcessing(false)

方案2:先缓存文件内容再复用

如果不想用Multicast,也可以先把文件内容缓存到Header中,在第一次发送完成后重新设置回消息体,供第二个路径使用:

from("{{csv.generation}}")
    .setHeader("dynamicFileName", constant("Main.csv"))
    // 将文件内容缓存到自定义Header中
    .setHeader("cachedCsvContent", body())
    // 发送到主SFTP路径
    .toD("sftp://${properties:ses.sftp.user}@{{ses.sftp.host}}:${properties:${header.country}.sftp.port}${properties:${header.country}.sftp.rdir}?username=${properties:ses.sftp.user}&privateKeyFile={{sftp.prvt.key.path}}&preferredAuthentications=publickey&knownHostsFile={{knownHost.file.path}}&fileName=${header.dynamicFileName}&doneFileName=${header.dynamicFileName}{{cco.files.ready.ext}}")
    .log("target csv file has been saved successfully at ${properties:${header.country}.sftp.rdir} SFTP location")
    // 把缓存的内容重新设置回消息体
    .setBody(header("cachedCsvContent"))
    // 发送到第二个路径并指定文件名
    .to("{{save.copy.to.another.path}}?fileName=${header.dynamicFileName}")
    .log("Created a copy on Fabric {{save.copy.to.another.path}}${header.dynamicFileName}");

关键注意点

  • 一定要给第二个to端点指定fileName参数,否则Camel会默认使用Exchange的ID作为文件名,这就是你错误日志中出现/opt/datafiles/5BBCC953F1D3167-0000000000000002这个奇怪文件名的原因。
  • 如果你的CSV文件是大文件,缓存到Header可能会占用较多内存,这种情况下优先选择Multicast方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 21:04:10