Apache Camel文件下载异常:仅最后一个文件可下载,其余被遗漏
问题原因分析
你的代码存在三个核心问题导致仅最后一个URL被处理:
错误的字符串拆分逻辑
输入文件中URL是每行一个,但你使用split(" ")按空格拆分。实际文件内容的分隔符是换行符(\n或\r\n),这会导致拆分结果不符合预期:要么整个文件内容被当成一个元素,要么拆分出包含换行的无效元素,进而影响后续处理。用
File处理URL字符串的错误用法
直接将URL字符串传入new File(s)是错误的——URL是网络资源标识,不是本地文件路径。在Windows系统下,https://github.com/a.zip会被转换为https:\github.com\a.zip这种无效的File路径,不仅无法正确提取文件名,还可能触发IO异常。异常被静默忽略
catch块中仅调用e.getMessage()却未输出任何日志,导致第一个URL处理失败时无法察觉异常,误以为是被"遗漏"。
修复后的代码方案
方案1:修正Process内的处理逻辑(快速修复)
import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.nio.file.Files; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.util.Arrays; import org.apache.camel.builder.RouteBuilder; import org.springframework.stereotype.Component; @Component public class Download extends RouteBuilder{ @Override public void configure() throws Exception { from("file:files/input") .routeId("downloadInitId") .to("direct:downloadFiles"); from("direct:downloadFiles") .routeId("downloadProcessId") .process(p -> { String body = p.getIn().getBody(String.class); // 按任意空白字符(换行、空格、制表符等)拆分,适配不同换行格式 Arrays.stream(body.split("\\s+")) // 过滤空字符串(避免文件首尾空行导致的无效元素) .filter(s -> !s.trim().isEmpty()) .forEach(s -> { try { URL url = new URL(s); // 从URL路径直接提取文件名,无需使用File String fileName = url.getPath().substring(url.getPath().lastIndexOf("/") + 1); System.out.println(fileName); System.out.println(s); try (InputStream in = url.openStream()) { // 使用try-with-resources自动关闭输入流,避免资源泄漏 Files.copy(in, Paths.get(".\\files\\download\\output\\" + fileName), StandardCopyOption.REPLACE_EXISTING); } } catch (IOException e) { // 打印异常日志,便于排查问题 System.err.println("处理URL失败: " + s); e.printStackTrace(); } }); }); } }
方案2:使用Camel Split组件(更符合Camel路由规范)
Camel提供了专门的Split组件来处理拆分逻辑,比手动循环更优雅且易于维护:
import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.nio.file.Files; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import org.apache.camel.builder.RouteBuilder; import org.springframework.stereotype.Component; @Component public class Download extends RouteBuilder{ @Override public void configure() throws Exception { from("file:files/input") .routeId("downloadInitId") // 按换行符拆分每行,同时过滤空行 .split(body().tokenize("\n")).streaming() .filter(body().isNotEmpty()) .to("direct:downloadSingleFile"); from("direct:downloadSingleFile") .routeId("downloadProcessId") .process(p -> { String urlStr = p.getIn().getBody(String.class).trim(); URL url = new URL(urlStr); String fileName = url.getPath().substring(url.getPath().lastIndexOf("/") + 1); System.out.println("正在下载: " + fileName); try (InputStream in = url.openStream()) { Files.copy(in, Paths.get(".\\files\\download\\output\\" + fileName), StandardCopyOption.REPLACE_EXISTING); } }) .onException(IOException.class) .log("下载失败: ${body}") .handled(true); } }
关键修复点说明
- 改用
split("\\s+")或Camel的tokenize("\n")拆分每行数据,适配换行符分隔的输入格式。 - 通过
URL.getPath()提取文件名,避免使用File处理URL的错误方式。 - 使用try-with-resources自动关闭输入流,防止资源泄漏。
- 添加异常日志打印,便于定位处理失败的URL。
- 过滤空字符串/空行,避免无效的URL处理。
内容的提问来源于stack exchange,提问作者Ricky V.
相关产品推荐
相关产品推荐

