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

如何解决Camel-HDFS在Windows递归上传时的路径非法字符问题

问题描述

我用Apache Camel编写路由,将Windows本地文件递归上传到HDFS,代码如下:

public class FileRouteBuilder extends EndpointRouteBuilder {

    @Override
    public void configure() throws Exception {
        from(file("C://Users/pcn/Desktop/test").noop(true).recursive(true))
                .process(new FileProcessor())
                .to(hdfs("localhost:9000/2209212/"))
                .log(LoggingLevel.DEBUG, "completed");
    }
}

开启recursive选项后,出现路径非法字符错误,错误栈如下:

java.lang.IllegalArgumentException: Illegal character in path at index 33: hdfs://localhost:9000/220922/rec\test4.txt
    at java.base/java.net.URI.create(URI.java:883)
    at org.apache.camel.component.hdfs.HdfsInfoFactory.newFileSystem(HdfsInfoFactory.java:102)
    at org.apache.camel.component.hdfs.HdfsInfoFactory.newHdfsInfoWithoutAuth(HdfsInfoFactory.java:63)
    at org.apache.camel.component.hdfs.HdfsInfoFactory.newHdfsInfoWithoutAuth(HdfsInfoFactory.java:41)
    at org.apache.camel.component.hdfs.HdfsOutputStream.createOutputStream(HdfsOutputStream.java:50)
    at org.apache.camel.component.hdfs.HdfsProducer.doProcess(HdfsProducer.java:205)
    at org.apache.camel.component.hdfs.HdfsProducer.process(HdfsProducer.java:188)
    at org.apache.camel.support.AsyncProcessorConverterHelper$ProcessorToAsyncProcessorBridge.process(AsyncProcessorConverterHelper.java:66)
    at org.apache.camel.processor.SendDynamicProcessor.lambda$process$0(SendDynamicProcessor.java:197)
    at org.apache.camel.support.cache.DefaultProducerCache.doInAsyncProducer(DefaultProducerCache.java:318)
    at org.apache.camel.processor.SendDynamicProcessor.process(SendDynamicProcessor.java:182)
    at org.apache.camel.processor.errorhandler.RedeliveryErrorHandler$SimpleTask.run(RedeliveryErrorHandler.java:469)
    at org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.schedule(DefaultReactiveExecutor.java:187)
    at org.apache.camel.impl.engine.DefaultReactiveExecutor.scheduleMain(DefaultReactiveExecutor.java:64)
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:184)
    at org.apache.camel.impl.engine.CamelInternalProcessor.process(CamelInternalProcessor.java:398)
    at org.apache.camel.component.file.GenericFileConsumer.processExchange(GenericFileConsumer.java:492)
    at org.apache.camel.component.file.GenericFileConsumer.processBatch(GenericFileConsumer.java:245)
    at org.apache.camel.component.file.GenericFileConsumer.poll(GenericFileConsumer.java:206)
    at org.apache.camel.support.ScheduledPollConsumer.doRun(ScheduledPollConsumer.java:197)
    at org.apache.camel.support.ScheduledPollConsumer.run(ScheduledPollConsumer.java:111)
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
    at java.base/java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305)
    at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at java.base/java.lang.Thread.run(Thread.java:829)

我尝试用自定义Processor替换路径中的反斜杠,但无效:

@Service
@Slf4j
public class FileProcessor implements Processor {

    @Override
    public void process(Exchange exchange) throws Exception {
        GenericFile body = exchange.getIn().getBody(GenericFile.class);
        body.setEndpointPath(exchange.getIn().getBody(GenericFile.class).getEndpointPath().replace("\/", "/"));
        body.setRelativeFilePath(exchange.getIn().getBody(GenericFile.class).getRelativeFilePath().replace("\/", "/"));
        body.setAbsoluteFilePath(exchange.getIn().getBody(GenericFile.class).getAbsoluteFilePath().replace("\/", "/"));

        exchange.getIn().setBody(body);

    }
}

也试过设置属性并用toD,结果一样。请问该怎么修复?

解决方案

方法1:配置File组件的路径分隔符

直接在File组件中指定pathSeparator为正斜杠,从根源上让递归扫描生成的相对路径统一使用正斜杠,无需额外处理:

from(file("C://Users/pcn/Desktop/test")
        .noop(true)
        .recursive(true)
        .pathSeparator("/")) // 强制使用正斜杠作为路径分隔符
    .to(hdfs("localhost:9000/2209212/"))
    .log(LoggingLevel.DEBUG, "completed");

方法2:修改Processor的路径处理逻辑

之前的Processor无效是因为没有修改HDFS组件实际依赖的Exchange属性。HDFS组件构建目标路径时,会读取CamelFileName这类属性,而非GenericFile的路径字段。修改后的Processor如下:

@Service
@Slf4j
public class FileProcessor implements Processor {

    @Override
    public void process(Exchange exchange) throws Exception {
        String relativePath = exchange.getIn().getHeader(Exchange.FILE_NAME, String.class);
        if (relativePath != null) {
            // 替换Windows反斜杠为正斜杠
            String normalizedPath = relativePath.replace("\\", "/");
            exchange.getIn().setHeader(Exchange.FILE_NAME, normalizedPath);
        }
    }
}

方法3:用toD动态构建目标路径

如果需要更灵活的路径控制,可通过toD动态拼接路径并替换反斜杠:

from(file("C://Users/pcn/Desktop/test").noop(true).recursive(true))
    .toD("hdfs://localhost:9000/2209212/${header.CamelFileName.replace('\\\\', '/')}")
    .log(LoggingLevel.DEBUG, "completed");

注意这里需要转义反斜杠,用\\\\表示单个反斜杠。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 12:10:49