我正在编写一个代码,从前端接收后发送多张大小为10MB的大图片。目的是在后台处理图像并将响应立即发送到前端界面。
下面是接收前端请求的代码
@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")));
}
下面的代码使用 webclient 将收到的图像发送到其他服务器
异步服务
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"));
});
}
当图像大小为 KB 时,它工作正常,但对于更大的图像文件大小,则会出现如下错误。
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]
当请求被处理并返回给客户端时,以下块无法完成。
.doOnNext(map -> {
asynchronousService.handlerAsync(map).subscribe();
})
尝试使用
.then()
来代替并尝试一下。
或者,通过属性
Codecs
更改 spring.codec.max-in-memory-size
的内存大小。
在我们的实际应用中,我们有很多类似这样的上传案例。 例如。从我们的客户端上传文件,服务器端接收它并将其发送到其他存储,例如S3或Sftp等。所有情况都运行良好。