Affects: 6.0.11

With the WebClient upload snippet below, trying to upload file with some parameters. The body sent have unnecessary headers submitted. When I tested with just html form upload, upload process was successful, however with webclient, error was occured. As I do not have access to the endpoint nor have no idea how they process at the endpoint, the only differences I saw was they payload sent.

MultipartBodyBuilder builder = new MultipartBodyBuilder();
builder.part("data_file", new FileSystemResource(uFile));
builder.part("user_id", "test_user");
builder.part("password", "testPwd");
builder.part("up_type", "2");
builder.part("kind", "35");
builder.part("kind_name", "SAMPLE UPLOAD TEST");
builder.part("file_name", "XXXXX.csv");

WebClient client = WebClient.builder()
        .clientConnector(new ReactorClientHttpConnector(
                HttpClient.create().option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 180000).compress(true).followRedirect(true)))
        .filter(new LoggingExchangeFilterFunction(true)).build();
String httpStatusMono = client.post().uri(uploadUrl).contentType(MediaType.MULTIPART_FORM_DATA)
        .body(BodyInserters.fromMultipartData(builder.build()))
        .retrieve().bodyToMono(String.class).block();

System.out.println("Http Status : " + httpStatusMono);

Payload Sent through browser (Expected Value)

------WebKitFormBoundaryZrXyDAsX9SPUu09A
Content-Disposition: form-data; name="data_file"; filename="XXXXX.csv"
Content-Type: text/csv
Content-Length: 135

S,1,test_user,20230825,40
D,9999,0012102,5,20230904,,01,R000000,,20230908,,,,
D,9999,0037669,6,20230905,,01,R000000,,20230909,,,,
E,4
------WebKitFormBoundaryZrXyDAsX9SPUu09A
Content-Disposition: form-data; name="user_id"

test_user
------WebKitFormBoundaryZrXyDAsX9SPUu09A
Content-Disposition: form-data; name="password"

testPwd
------WebKitFormBoundaryZrXyDAsX9SPUu09A
Content-Disposition: form-data; name="up_type"

2
------WebKitFormBoundaryZrXyDAsX9SPUu09A
Content-Disposition: form-data; name="kind"

35
------WebKitFormBoundaryZrXyDAsX9SPUu09A
Content-Disposition: form-data; name="kind_name"

SAMPLE UPLOAD TEST
------WebKitFormBoundaryZrXyDAsX9SPUu09A
Content-Disposition: form-data; name="file_name"

XXXXX.csv
------WebKitFormBoundaryZrXyDAsX9SPUu09A--

Payload sent through WebClient (Error occured)

--KNeG0Ctz9Py2S3-WVI-GQBu27kptq1DOrxSoDb
Content-Disposition: form-data; name="data_file"; filename="XXXXX.csv"
Content-Type: text/csv
Content-Length: 135

S,1,test_user,20230825,40
D,9999,0012102,5,20230904,,01,R000000,,20230908,,,,
D,9999,0037669,6,20230905,,01,R000000,,20230909,,,,
E,4
--KNeG0Ctz9Py2S3-WVI-GQBu27kptq1DOrxSoDb
Content-Disposition: form-data; name="user_id"
Content-Type: text/plain;charset=UTF-8
Content-Length: 8

test_user
--KNeG0Ctz9Py2S3-WVI-GQBu27kptq1DOrxSoDb
Content-Disposition: form-data; name="password"
Content-Type: text/plain;charset=UTF-8
Content-Length: 8

testPwd
--KNeG0Ctz9Py2S3-WVI-GQBu27kptq1DOrxSoDb
Content-Disposition: form-data; name="up_type"
Content-Type: text/plain;charset=UTF-8
Content-Length: 1

2
--KNeG0Ctz9Py2S3-WVI-GQBu27kptq1DOrxSoDb
Content-Disposition: form-data; name="kind"
Content-Type: text/plain;charset=UTF-8
Content-Length: 2

35
--KNeG0Ctz9Py2S3-WVI-GQBu27kptq1DOrxSoDb
Content-Disposition: form-data; name="kind_name"
Content-Type: text/plain;charset=UTF-8
Content-Length: 52

SAMPLE UPLOAD TEST
--KNeG0Ctz9Py2S3-WVI-GQBu27kptq1DOrxSoDb
Content-Disposition: form-data; name="file_name"
Content-Type: text/plain;charset=UTF-8
Content-Length: 24

XXXXX.csv
--KNeG0Ctz9Py2S3-WVI-GQBu27kptq1DOrxSoDb--

As you can see, the only difference is the "Content-Type" and "Content-Length" added in the headers of each parameter. I tried several approaches in setting of the body but no avail. I noticed that in MultipartHttpMessageWriter.java, content-type is always included in sending the payload so there is no way to exclude it. Is there's a way to override MultipartHttpMessageWriter with custom Writer class?

Comment From: rstoyanchev

MultipartHttpMessageWriter encodes individual parts through a list of HttpMessageWriter's that support specific Java types and media formats. You can customize this list:

WebClient webClient = WebClient.builder()
        .baseUrl("...")
        .codecs(config -> config.defaultCodecs().multipartCodecs().encoder(..).writer(...))
        .build();

For files, you can use ResourceEncoder. For text, CharSequenceEncoder is wrapped with EncoderHttpMessageWriter and that's what adds content-length and content-type. You could instead wrap CharSequenceEncoder with a simpler HttpMessageWriter that delegates CharSequenceEncoder doesn't set any headers.