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

Webflux与Flux<String>处理响应时的空格丢失问题排查

解决Flux响应丢失空格的问题

问题分析

调用返回TEXT_EVENT_STREAM类型的Flux接口时,拼接后的输出丢失所有空格,核心原因可能是客户端对SSE事件的解析逻辑未正确保留空格,或服务端返回的事件格式存在特殊处理。

排查与解决步骤

1. 确认服务端原始响应是否包含空格

先通过curl或Postman直接调用接口,查看原始SSE响应内容,验证每个data字段是否包含预期的空格:

curl -X POST \
  -H "Content-Type: application/json" \
  -d '{"你的请求体内容"}' \
  "你的baseUrl/你的uri?temperature=0.3"

如果原始响应就没有空格,需联系服务端排查;若原始响应有空格,继续客户端排查。

2. 改用SseEvent解析完整事件内容

WebClient默认的bodyToFlux<String>可能无法正确处理SSE事件中的空格(比如空格作为单独事件返回时被过滤),改用SseEvent类型解析可确保完整获取每个事件的data字段:

Flux<SseEvent> eventStream = webClientBuilder
        .clientConnector(new ReactorClientHttpConnector(httpClient))
        .baseUrl(baseUrl)
        .build()
        .post()
        .uri(uriBuilder -> uriBuilder.path(uri).queryParam("temperature", "0.3").build(llmType))
        .accept(MediaType.TEXT_EVENT_STREAM)
        .headers(httpHeaders -> httpHeaders.addAll(headers))
        .bodyValue(body)
        .retrieve()
        .bodyToFlux(SseEvent.class);

List<String> resultList = eventStream
        .map(SseEvent::data)
        .doOnNext(event -> {
            log.info("事件内容: '{}' 长度: {}", event, event.length());
        })
        .collectList()
        .block();

log.info(String.join("", resultList));

3. 配置StringDecoder禁用自动修剪

如果WebClient的字符串解码器默认修剪了空白字符,可自定义解码器配置,保留所有原始字符:

WebClient webClient = webClientBuilder
        .clientConnector(new ReactorClientHttpConnector(httpClient))
        .baseUrl(baseUrl)
        .codecs(configurer -> {
            // 禁用字符串解码器的末尾换行修剪,保留原始空格
            configurer.defaultCodecs().stringDecoder(
                new StringDecoder(MediaType.ALL, StandardCharsets.UTF_8, false)
            );
        })
        .build();

4. 检查是否存在URL转义情况

若服务端返回的空格被转义为%20,需在客户端对事件内容进行URL解码:

import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;

// ...
List<String> resultList = eventStream
        .map(event -> URLDecoder.decode(event, StandardCharsets.UTF_8))
        .doOnNext(event -> {
            log.info("事件内容: '{}' 长度: {}", event, event.length());
        })
        .collectList()
        .block();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 16:20:18