Problem: I have an interface that needs to pass a file and a uri parameter, I use WebClient HTTP Interface , like this:
@PostExchange(value = "/fileUpload",contentType = MediaType.MULTIPART_FORM_DATA_VALUE)
BaseEntity upload( @RequestPart("file") HttpEntity param, @RequestParam("storageType") String storageType);
call this method,the server can not receive the file 。 in the code : org.springframework.web.service.invoker.HttpRequestValues.Builder#build
if (!CollectionUtils.isEmpty(this.requestParams)) {
boolean isFormData = (this.headers != null &&
MediaType.APPLICATION_FORM_URLENCODED.equals(this.headers.getContentType()));
if (isFormData) {
Assert.isTrue(bodyValue == null && this.body == null, "Expected body or request params, not both");
bodyValue = new LinkedMultiValueMap<>(this.requestParams);
}
else if (uri != null) {
uri = UriComponentsBuilder.fromUri(uri)
.queryParams(UriUtils.encodeQueryParams(this.requestParams))
.build(true)
.toUri();
}
else {
uriVars = (uriVars.isEmpty() ? new HashMap<>() : uriVars);
uriTemplate = appendQueryParams(uriTemplate, uriVars, this.requestParams);
}
}
else if (this.multipartBuilder != null) {
Assert.isTrue(bodyValue == null && this.body == null, "Expected body or request parts, not both");
bodyValue = this.multipartBuilder.build();
}
if the request have requestParams, the multipartBuilder won't handle it.
Comment From: rstoyanchev
We can improve the logic to first make a decision if the request is multipart by checking the content-type and the presence of MultipartBodyBuilder
, and if it is then prepare it as such.
When it comes to @RequestParam
, the term request parameter comes from the Servlet API, and could mean a parameter from the query of the URI, from the body of a form data request, or from the parts of a multipart request. When handling a request it's possible to check all places, but when preparing a request it's less clear what it should be.
For a multipart request at least, we can expect use of @RequestPart
if it needs to be in the body, but otherwise @RequestParam
becomes a query parameter. For a form data request however, @RequestParam
would have to remain as is, i.e. always in the body as there is no way to differentiate one from the other.