Skip to content

Binary data in POST multipart request is unmarshalled incorrectly [SPR-13096] #17687

@spring-projects-issues

Description

@spring-projects-issues

Simone Russo opened SPR-13096 and commented

Example server code:

@RequestMapping(value = "/", method = RequestMethod.POST, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@ResponseStatus(value = HttpStatus.CREATED)
public void addItem(
   @RequestPart("objectValue") byte[] objectValue,
   @RequestPart("metadata") SomeJsonDeserialisableClass metadata
) {
   /// ...
}

Example client:

public void makeRequest(byte[] content, SomeJsonDeserialisableClass  metadata) {
      HttpHeaders octetStreamHeader = new HttpHeaders();
      octetStreamHeader.setContentType(MediaType.APPLICATION_OCTET_STREAM);
      octetStreamHeader.setContentLength(content.length);

      HttpHeaders jsonHeader = new HttpHeaders();
      jsonHeader.setContentType(MediaType.APPLICATION_JSON);

      MultiValueMap<String, Object> requestParts = new LinkedMultiValueMap<>();
      requestParts.add("objectValue", new HttpEntity<>(content, octetStreamHeader));
      requestParts.add("metadata", new HttpEntity<>(metadata, jsonHeader));

      URI requestUri = //endpoint url..

      HttpHeaders requestHeaders = new HttpHeaders();
      requestHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);

      ResponseEntity<Void> response = restOperations.exchange(
         requestUri,
         HttpMethod.POST,
         new RequestEntity<>(requestParts, requestHeaders, HttpMethod.POST, requestUri),
         Void.class
      );
   }

If the byte array passed to the client method contains negative values, the byte array received by the controller method on the server side will have different contents.

This happens because:

  1. In org.springframework.web.multipart.commons.CommonsFileUploadSupport, the original binary data is read as a string in the following line:
value = fileItem.getString(partEncoding);
  1. That string is then converted back into a byte array in org.springframework.web.multipart.support.RequestPartServletServerHttpRequest in this line:
return new ByteArrayInputStream(paramValue.getBytes(FORM_CHARSET));

Where FORM_CHARSET is hardcoded to "UTF-8"


Affects: 4.1.6

Metadata

Metadata

Assignees

Labels

in: webIssues in web modules (web, webmvc, webflux, websocket)type: bugA general bug

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions