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

如何通过Camel-Jetty组件流式上传大文件以避免OutOfMemoryError

问题

使用Camel-Jetty组件时,如何通过multipart/form-data格式流式上传大文件(无需将整个文件加载到内存即可立即处理)?当前上传大文件时抛出内存溢出错误:

java.lang.IllegalStateException: java.lang.OutOfMemoryError: Java heap space

当前使用的Camel路由代码如下:

public class InputHttpRoute extends RouteBuilder {
    @Override
    public void configure() throws Exception {

        from(http())
                .noStreamCaching()
                .process(e -> {
                    e.getIn(AttachmentMessage.class).getAttachments()
                            .forEach((s, dataHandler) -> {
                                InputStream files = null;
                                try {
                                    files = dataHandler.getInputStream();
                                    byte[] buffer = new byte[10500];
                                    int b;
                                    while ((b = files.read(buffer)) != -1) {
                                        // Convert byte to character
                                        String data = new String(buffer, 0, b);
                                        System.err.println(data);
                                    }
                                } catch (IOException ex) {
                                    throw new RuntimeException(ex);
                                }
                            });

                });
        //  .setBody(constant("xxx"))
        ;
    }

    private static String http() {
        return new StringBuilder("jetty:http://0.0.0.0:8787/email/myservice")
                .append("?httpMethodRestrict=")
                .append("POST")
                .append("&disableStreamCache=true")
                .append("&eagerCheckContentAvailable=true")
                .append("&exchangePattern=InOnly")
                .append("&chunked=true")
                .append("&requestBufferSize=0")
                .append("&responseBufferSize=0")

                /*      .append("&requestBufferSize=")
                      .append(100)
                      .append("&requestHeaderSize=")
                      .append(100)
                      .append("&disableStreamCache=true")*/
                .toString();
    }
}

解决方案

1. 配置Jetty端点,强制流式处理Multipart

Jetty默认会将Multipart内容缓存到内存或临时文件,需通过参数配置强制流式处理:

  • 移除eagerCheckContentAvailable=true:该参数会让Jetty提前读取整个请求到内存,与流式处理冲突
  • 添加multipartConfig参数:设置不限制文件大小、跳过内存缓存阈值

修改后的http()方法:

private static String http() {
    return new StringBuilder("jetty:http://0.0.0.0:8787/email/myservice")
            .append("?httpMethodRestrict=POST")
            .append("&disableStreamCache=true")
            .append("&exchangePattern=InOnly")
            .append("&chunked=true")
            .append("&requestBufferSize=0")
            .append("&responseBufferSize=0")
            .append("&multipartConfig={{location=/, maxFileSize=-1, maxRequestSize=-1, fileSizeThreshold=0}}")
            .toString();
}

2. 优化文件处理逻辑,减少内存占用

  • 使用try-with-resources自动关闭输入流,避免资源泄漏
  • 避免将二进制字节直接转成String(非文本文件会乱码且增加内存开销),直接操作字节流即可
  • 使用标准大小的缓冲区(如8KB),减少内存波动

修改后的Processor逻辑:

.process(e -> {
    AttachmentMessage attachmentMsg = e.getIn(AttachmentMessage.class);
    attachmentMsg.getAttachments().forEach((fileName, dataHandler) -> {
        try (InputStream inputStream = dataHandler.getInputStream()) {
            byte[] buffer = new byte[8192];
            int readBytes;
            while ((readBytes = inputStream.read(buffer)) != -1) {
                // 此处编写流式处理逻辑,比如写入文件、转发到消息队列等
                // 示例:Files.write(Paths.get("/tmp/" + fileName), buffer, 0, readBytes, StandardOpenOption.CREATE, StandardOpenOption.APPEND);
            }
        } catch (IOException ex) {
            throw new RuntimeException("处理文件[" + fileName + "]失败", ex);
        }
    });
})

3. 额外优化

  • 全局禁用StreamCaching:在Camel上下文初始化时添加camelContext.getStreamCachingStrategy().setEnabled(false);,确保没有隐式的流缓存
  • 调整JVM堆内存参数(如-Xmx512m)作为兜底,但这不是解决内存溢出的根本方案

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 12:35:05