Reputation: 462
I am writing a code to send multiple big images of size 10MB after receiving from the front end. The objective is to do the processing of the images in the background and send the response immediately to front end interface.
Below is the piece of code which receive the request from frontend
@PostMapping(value = "/submit")
public Mono<ResponseEntity<String>> handleFormSubmit(ServerWebExchange serverWebExchange) {
return serverWebExchange.getMultipartData()
.filter(map -> !CollectionUtils.isEmpty(map))
.doOnNext(map -> {
asynchronousService.handlerAsync(map).subscribe();
})
.map(filePart -> ResponseEntity.ok("success"))
.switchIfEmpty(Mono.just(ResponseEntity.badRequest().body("bad")));
}
Below piece of code send the images received to the other server using webclient
Asynchronous Service
public Mono<Void> handlerAsync(MultiValueMap<String,Part> fileParts) {
MultipartBodyBuilder multipartBodyBuilder = new MultipartBodyBuilder();
fileParts.forEach((key,value)->{
FilePart filePart= (FilePart) value.get(0);
multipartBodyBuilder.asyncPart(filePart.name(), filePart.content(), DataBuffer.class)
.filename(filePart.filename()).header("DocType","INSPECTION");
});
MultiValueMap<String, HttpEntity<?>> requestBody = multipartBodyBuilder.build();
return WebClient.builder()
.codecs(clientCodecConfigurer -> clientCodecConfigurer.defaultCodecs().maxInMemorySize(1024*1024*16))
.build()
.post().uri("http://localhost:8081/receive")
.bodyValue(requestBody)
.retrieve()
.onStatus(httpStatusCode -> httpStatusCode.is4xxClientError() || httpStatusCode.is5xxServerError(), cr ->
cr.createException().map(webClientResponseException -> {
System.out.println(webClientResponseException.getResponseBodyAsString());
System.out.println(webClientResponseException.getStatusCode());
return webClientResponseException;
}))
.bodyToMono(Void.class)
.retryWhen(Retry.fixedDelay(2, Duration.ofSeconds(2)))
.onErrorResume(throwable -> {
if (Exceptions.isRetryExhausted(throwable)) {
Mono.error(new RuntimeException("retry exhausted"));
}
return Mono.error(new RuntimeException("error"));
});
}
It is working fine when the images are in KB size but for bigger image file size it is giving an error as below.
java.nio.file.NoSuchFileException: /tmp/spring-multipart-12155021382861713953/10508329666633429299.multipart
at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:92) ~[na:na]
at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:106) ~[na:na]
at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111) ~[na:na]
at java.base/sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:218) ~[na:na]
at java.base/java.nio.file.Files.newByteChannel(Files.java:380) ~[na:na]
Upvotes: 0
Views: 26
Reputation: 9321
The following block could not finished when the request is handled and returned to the client.
.doOnNext(map -> {
asynchronousService.handlerAsync(map).subscribe();
})
Try to use .then()
instead and have a try.
Alternatively, change the in-memory size of Codecs
via the property spring.codec.max-in-memory-size
.
In our real-world applications, we have a lot of upload cases similar to this. eg. Uploading files from our clients, the server side receives it and sends it to other storage, such as S3 or Sftp, etc. All cases worked well.
Check my example of uploading files and storing in MongoDB.
Upvotes: 0