I have tested following code in Spring boot version 2.3.7.RELEASE and 2.4.2
@RestController
public class DemoController {
@PostMapping("/transferTo")
Flux<String> transferTo(@RequestPart("fileParts") Flux<FilePart> parts) {
return parts.concatMap(filePart -> createTempFile(filePart.filename())
.flatMap(tempFile -> filePart.transferTo(tempFile)
.then(Mono.just("File length: " + tempFile.toFile().length()))));
}
private Mono<Path> createTempFile(String suffix) {
return Mono.defer(() -> {
try {
return Mono.just(Files.createTempFile("MultipartIntegrationTests", suffix));
} catch (IOException ex) {
return Mono.error(ex);
}
})
.subscribeOn(Schedulers.boundedElastic());
}
}
Response on http://localhost:8080/transferTo With 2.3.7.RELEASE File length: 13 With 2.4.2 File length: 0
File gets uploaded in both versions but I am unable to get content in 2.4.2 version inside .then()
operator.
Sample to reproduce the issue - https://github.com/anupam-contaque/webflux-multipart-demo
Comment From: rstoyanchev
@anupam-contaque this doesn't look right:
filePart.transferTo(tempFile).then(Mono.just("File length: " + tempFile.toFile().length()))
The call to File#length
is not deferred may happen before transferTo
has completed. It's possible that worked in 2.3.x but that's by chance, depending on how transferTo
was executed (asynchronously or not).
Here are a couple of ways to do it:
filePart.transferTo(tempFile).then(Mono.fromRunnable(() -> "File length: " + tempFile.toFile().length()))
filePart.transferTo(tempFile).doOnSuccess(() -> "File length: " + tempFile.toFile().length()))