将Flux<DataBuffer>封装到自定义对象后WebClient上传文件为空如何解决
问题根因
0字节问题的核心原因有两点:
- Spring WebClient的
exchangeToMono方法会在回调返回的Mono完成后自动释放HTTP连接,你在回调中仅将response.bodyToFlux(DataBuffer::class.java)的流引用封装到Mediator对象返回,此时并未消费响应体流,连接释放后这个Flux就会变成无效空流,后续上传时自然没有数据。 - 你在
runBlocking中调用subscribe()触发流执行,subscribe()是异步非阻塞方法,会立刻返回,runBlocking不等流执行完成就退出,也可能导致整个流程提前终止。
修复方案
将上传逻辑放在exchangeToMono的回调内部执行,保证下载连接未释放时就传递响应体流到上传逻辑,同时调整流的触发方式确保流程执行完成,修改后代码如下:
import kotlinx.coroutines.reactive.awaitSingle import org.springframework.http.MediaType import org.springframework.http.ResponseEntity import org.springframework.web.reactive.function.client.WebClient import reactor.core.publisher.Mono runBlocking { downloadAndUpload().awaitSingle() } private fun downloadAndUpload(): Mono<ResponseEntity<Void>> { return WebClient.create("https://server.com/assets/file.pdf") .get() .exchangeToMono { downloadResponse -> // 直接在回调内完成上传,此时下载连接仍处于有效状态 WebClient.create("http://localhost:3000/upload") .put() .contentType(MediaType.APPLICATION_OCTET_STREAM) .body(downloadResponse.bodyToFlux(DataBuffer::class.java), DataBuffer::class.java) .retrieve() .toBodilessEntity() } .doOnError { e -> println("流程执行出错:${e.message}") } }
额外注意事项
- 大文件传输时建议调整Spring WebClient的缓冲区配置,避免OOM问题。
- 正常消费流的场景下Spring会自动管理DataBuffer的内存释放,若有自定义截断、跳过流的操作,需要手动调用
DataBufferUtils.release(dataBuffer)避免内存泄漏。
内容的提问来源于stack exchange,提问作者Vahid
相关产品推荐
相关产品推荐

