Spring WebClient: не найдено подходящего писателя для части: param1
Я пытаюсь загрузить файл с некоторыми другими текстовыми атрибутами с помощью Spring 5 Webclient. Однако я получаю сообщение об ошибке: Ниже приведен код:
MultipartBodyBuilder bodyBuilder = new MultipartBodyBuilder();
bodyBuilder.part("myFile", uploadedFile.getBytes());
bodyBuilder.part("param1", formType, MediaType.TEXT_PLAIN).header("Content-Disposition", "form-data; name=param1").header("Content-type", "text/plain");
bodyBuilder.part("param2", orgId, MediaType.TEXT_PLAIN).header("Content-Disposition", "form-data; name=param2").header("Content-type", "text/plain");
bodyBuilder.part("param3", ignoreCheck, MediaType.TEXT_PLAIN).header("Content-Disposition", "form-data; name=param3").header("Content-type", "text/plain");
bodyBuilder.part("param4", forSentiLink, MediaType.TEXT_PLAIN).header("Content-Disposition", "form-data; name=param4").header("Content-type", "text/plain");
return webclient.post()
.uri(myUri)
.contentType(MediaType.MULTIPART_FORM_DATA)
.body(BodyInserters.fromMultipartData(bodyBuilder.build()))
.exchange()
.flatMap(response -> response.bodyToMono(MyDto.class))
.flux()
.blockFirst();
Этот код используется для создания данных формы с некоторыми текстовыми полями и полем файла.
Но при попытке запустить код я получаю сообщение об ошибке:
Устранено [org.springframework.core.codec.CodecException: для part: param1 не найден подходящий писатель]
org.springframework.core.codec.CodecException: No suitable writer found for part: param1
at org.springframework.http.codec.multipart.MultipartHttpMessageWriter.encodePart(MultipartHttpMessageWriter.java:299)
at org.springframework.http.codec.multipart.MultipartHttpMessageWriter.lambda$encodePartValues$4(MultipartHttpMessageWriter.java:252)
at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.drain(FluxConcatMap.java:368)
at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.onSubscribe(FluxConcatMap.java:212)
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onSubscribe(FluxOnAssembly.java:432)
at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:139)
at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:63)
at reactor.core.publisher.FluxOnAssembly.subscribe(FluxOnAssembly.java:122)
at reactor.core.publisher.FluxConcatMap.subscribe(FluxConcatMap.java:121)
at reactor.core.publisher.FluxOnAssembly.subscribe(FluxOnAssembly.java:122)
at reactor.core.publisher.Flux.subscribe(Flux.java:7938)
at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.drain(FluxConcatMap.java:442)
at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.onSubscribe(FluxConcatMap.java:212)
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onSubscribe(FluxOnAssembly.java:432)
at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:139)
at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:63)
at reactor.core.publisher.FluxOnAssembly.subscribe(FluxOnAssembly.java:122)
at reactor.core.publisher.FluxConcatMap.subscribe(FluxConcatMap.java:121)
at reactor.core.publisher.FluxOnAssembly.subscribe(FluxOnAssembly.java:122)
at reactor.core.publisher.Flux.subscribe(Flux.java:7938)
at reactor.core.publisher.FluxConcatArray$ConcatArraySubscriber.onComplete(FluxConcatArray.java:207)
at reactor.core.publisher.FluxConcatArray.subscribe(FluxConcatArray.java:80)
at reactor.core.publisher.FluxOnAssembly.subscribe(FluxOnAssembly.java:117)
at reactor.core.publisher.FluxContextStart.subscribe(FluxContextStart.java:49)
at reactor.core.publisher.FluxMapFuseable.subscribe(FluxMapFuseable.java:63)
at reactor.core.publisher.FluxOnAssembly.subscribe(FluxOnAssembly.java:122)
at reactor.core.publisher.Flux.subscribe(Flux.java:7938)
at reactor.netty.channel.MonoSendMany.subscribe(MonoSendMany.java:80)
at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:153)
at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:56)
at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:61)
at reactor.core.publisher.Mono.subscribe(Mono.java:3877)
at reactor.core.publisher.FluxConcatIterable$ConcatIterableSubscriber.onComplete(FluxConcatIterable.java:146)
at reactor.core.publisher.FluxConcatIterable.subscribe(FluxConcatIterable.java:60)
at reactor.core.publisher.FluxOnAssembly.subscribe(FluxOnAssembly.java:122)
at reactor.core.publisher.MonoIgnoreElements.subscribe(MonoIgnoreElements.java:37)
at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:61)
at reactor.core.publisher.Mono.subscribe(Mono.java:3877)
at reactor.core.publisher.FluxFlatMap.trySubscribeScalarMap(FluxFlatMap.java:200)
at reactor.core.publisher.MonoFlatMap.subscribe(MonoFlatMap.java:53)
at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:61)
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:61)
at reactor.netty.http.client.HttpClientConnect$HttpIOHandlerObserver.onStateChange(HttpClientConnect.java:438)
at reactor.netty.ReactorNetty$CompositeConnectionObserver.onStateChange(ReactorNetty.java:492)
at reactor.netty.resources.PooledConnectionProvider$DisposableAcquire.onStateChange(PooledConnectionProvider.java:503)
at reactor.netty.resources.PooledConnectionProvider$PooledConnection.onStateChange(PooledConnectionProvider.java:442)
at reactor.netty.channel.ChannelOperationsHandler.channelActive(ChannelOperationsHandler.java:60)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:225)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:211)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelActive(AbstractChannelHandlerContext.java:204)
at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelActive(CombinedChannelDuplexHandler.java:414)
at io.netty.channel.ChannelInboundHandlerAdapter.channelActive(ChannelInboundHandlerAdapter.java:69)
at io.netty.channel.CombinedChannelDuplexHandler.channelActive(CombinedChannelDuplexHandler.java:213)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:225)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:211)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelActive(AbstractChannelHandlerContext.java:204)
at reactor.netty.tcp.SslProvider$SslReadHandler.userEventTriggered(SslProvider.java:731)
at io.netty.channel.AbstractChannelHandlerContext.invokeUserEventTriggered(AbstractChannelHandlerContext.java:341)
at io.netty.channel.AbstractChannelHandlerContext.invokeUserEventTriggered(AbstractChannelHandlerContext.java:327)
at io.netty.channel.AbstractChannelHandlerContext.fireUserEventTriggered(AbstractChannelHandlerContext.java:319)
at io.netty.handler.logging.LoggingHandler.userEventTriggered(LoggingHandler.java:183)
at io.netty.channel.AbstractChannelHandlerContext.invokeUserEventTriggered(AbstractChannelHandlerContext.java:341)
at io.netty.channel.AbstractChannelHandlerContext.invokeUserEventTriggered(AbstractChannelHandlerContext.java:327)
at io.netty.channel.AbstractChannelHandlerContext.fireUserEventTriggered(AbstractChannelHandlerContext.java:319)
at io.netty.handler.ssl.SslHandler.setHandshakeSuccess(SslHandler.java:1753)
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1412)
at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1227)
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1274)
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:503)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:442)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:281)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1422)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:931)
at io.netty.channel.epoll.AbstractEpollStreamChannel$EpollStreamUnsafe.epollInReady(AbstractEpollStreamChannel.java:792)
at io.netty.channel.epoll.EpollEventLoop.processReady(EpollEventLoop.java:502)
at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:407)
at io.netty.util.concurrent.SingleThreadEventExecutor$6.run(SingleThreadEventExecutor.java:1050)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)
Серверная сторона этого API - python, где он пытается получить файл из запроса:
files={'files': open('file.txt','rb')}
values={'key' : 'value'}
r=requests.post(url,files=files,data=values)
{"status": 400, "message": "дополнительные ключи не разрешены @ data[u'param1']", "meta": {"status": 400, "msg": "дополнительные ключи не разрешены @ data[u'param1']"" ответ ": null}
1 ответ
String header1 = String.format("form-data; name=%s; filename=%s", "attach", myFile.getOriginalName());
bodyBuilder.part("attach", new ByteArrayResource(myFile.getBytes())).header("Content-Disposition", header1);
bodyBuilder.part("param1", param1);
bodyBuilder.part("param2", param2);
bodyBuilder.part("param3", param3);
bodyBuilder.part("param4", param4);
String respons = restClientService.getWebClient()
.post().uri(myuri)
.contentType(MediaType.MULTIPART_FORM_DATA)
.body(BodyInserters.fromMultipartData(bodyBuilder.build()))
.exchange()
.flatMap(response -> response.bodyToMono(MyDto.class))
.flux()
.blockFirst();