use of org.springframework.core.ResolvableTypeProvider in project spring-framework by spring-projects.
the class MultipartHttpMessageWriter method encodePart.
@SuppressWarnings("unchecked")
private <T> Flux<DataBuffer> encodePart(byte[] boundary, String name, T value, DataBufferFactory factory) {
MultipartHttpOutputMessage message = new MultipartHttpOutputMessage(factory);
HttpHeaders headers = message.getHeaders();
T body;
ResolvableType resolvableType = null;
if (value instanceof HttpEntity) {
HttpEntity<T> httpEntity = (HttpEntity<T>) value;
headers.putAll(httpEntity.getHeaders());
body = httpEntity.getBody();
Assert.state(body != null, "MultipartHttpMessageWriter only supports HttpEntity with body");
if (httpEntity instanceof ResolvableTypeProvider) {
resolvableType = ((ResolvableTypeProvider) httpEntity).getResolvableType();
}
} else {
body = value;
}
if (resolvableType == null) {
resolvableType = ResolvableType.forClass(body.getClass());
}
if (!headers.containsKey(HttpHeaders.CONTENT_DISPOSITION)) {
if (body instanceof Resource) {
headers.setContentDispositionFormData(name, ((Resource) body).getFilename());
} else if (resolvableType.resolve() == Resource.class) {
body = (T) Mono.from((Publisher<?>) body).doOnNext(o -> headers.setContentDispositionFormData(name, ((Resource) o).getFilename()));
} else {
headers.setContentDispositionFormData(name, null);
}
}
MediaType contentType = headers.getContentType();
final ResolvableType finalBodyType = resolvableType;
Optional<HttpMessageWriter<?>> writer = this.partWriters.stream().filter(partWriter -> partWriter.canWrite(finalBodyType, contentType)).findFirst();
if (!writer.isPresent()) {
return Flux.error(new CodecException("No suitable writer found for part: " + name));
}
Publisher<T> bodyPublisher = body instanceof Publisher ? (Publisher<T>) body : Mono.just(body);
// The writer will call MultipartHttpOutputMessage#write which doesn't actually write
// but only stores the body Flux and returns Mono.empty().
Mono<Void> partContentReady = ((HttpMessageWriter<T>) writer.get()).write(bodyPublisher, resolvableType, contentType, message, DEFAULT_HINTS);
// After partContentReady, we can access the part content from MultipartHttpOutputMessage
// and use it for writing to the actual request body
Flux<DataBuffer> partContent = partContentReady.thenMany(Flux.defer(message::getBody));
return Flux.concat(generateBoundaryLine(boundary, factory), partContent, generateNewLine(factory));
}
Aggregations