我经历过类似的票证(即 How to stream file from Multipart/form-data in Spring WebFlux ),但显然我的情况略有不同。
高级示例(无错误处理/无“空”检查):
Controller :
@ResponseStatus(code = HttpStatus.CREATED)
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public Mono<String> create(
@RequestPart(value = "images", required = false) final Flux<FilePart> images
) {
...service-call...
}
服务:
public Mono<String> create(
final Flux<FilePart> images
) {
MultipartBodyBuilder builder = new MultipartBodyBuilder();
return images
.filter(part -> Objects.nonNull(part.headers().getContentType()))
.filter(part ->
part.headers().getContentType().includes(MediaType.IMAGE_JPEG)
|| part.headers().getContentType().includes(MediaType.IMAGE_PNG)
)
.doOnNext(
part -> builder
.asyncPart("images", part.content(), DataBuffer.class)
.filename(part.filename())
)
.then(webClient.post()
.uri(URI_RESOURCE)
.contentType(MediaType.MULTIPART_FORM_DATA)
.body(BodyInserters.fromMultipartData(builder.build()))
.retrieve()
.bodyToMono(String.class)
);
}
问题是,客户端没有收到实际的“图像”:(我添加了一些doOnNext
来记录文件被添加到构建器的事实,所以我知道它们是。
我认为这是因为 .asyncPart("images", part.content(), DataBuffer.class)
但不确定如何避免/绕过这个内部发布商?
请注意, Controller 期望 Flux
基于我看到的所有建议;但是切换到普通 List<FilePart>
,解决了问题,虽然我认为在 WebFlux 中假设“阻止”请求是一种反模式,对吗?
最佳答案
问题是您的 then(webClient...)
block 已被调用,并且 MultipartBodyBuilder.build() 在请求开始时执行。您可以使用 Mono.defer
包裹 then
部分。
...
.then(Mono.defer(() -> {
return webClient.post()
.uri(URI_RESOURCE)
.contentType(MediaType.MULTIPART_FORM_DATA)
.body(BodyInserters.fromMultipartData(builder.build()))
.retrieve()
.bodyToMono(String.class);
}));
关于spring-webflux - Spring WebFlux - 通过 webClient 转发 FilePart,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74811994/