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.