Class FormHttpMessageConverter

java.lang.Object
org.springframework.http.converter.FormHttpMessageConverter
All Implemented Interfaces:
HttpMessageConverter<MultiValueMap<String,?>>
Direct Known Subclasses:
AllEncompassingFormHttpMessageConverter

public class FormHttpMessageConverter extends Object implements HttpMessageConverter<MultiValueMap<String,?>>
Implementation of HttpMessageConverter to read and write 'normal' HTML forms and also to write (but not read) multipart data (e.g. file uploads).

In other words, this converter can read and write the "application/x-www-form-urlencoded" media type as MultiValueMap<String, String>, and it can also write (but not read) the "multipart/form-data" and "multipart/mixed" media types as MultiValueMap<String, Object>.

Multipart Data

By default, "multipart/form-data" is used as the content type when writing multipart data. As of Spring Framework 5.2 it is also possible to write multipart data using other multipart subtypes such as "multipart/mixed" and "multipart/related", as long as the multipart subtype is registered as a supported media type and the desired multipart subtype is specified as the content type when writing the multipart data. Note that "multipart/mixed" is registered as a supported media type by default.

When writing multipart data, this converter uses other HttpMessageConverters to write the respective MIME parts. By default, basic converters are registered for byte array, String, and Resource. These can be overridden via setPartConverters(java.util.List<org.springframework.http.converter.HttpMessageConverter<?>>) or augmented via addPartConverter(org.springframework.http.converter.HttpMessageConverter<?>).

Examples

The following snippet shows how to submit an HTML form using the "multipart/form-data" content type.

 RestTemplate restTemplate = new RestTemplate();
 // AllEncompassingFormHttpMessageConverter is configured by default

 MultiValueMap<String, Object> form = new LinkedMultiValueMap<>();
 form.add("field 1", "value 1");
 form.add("field 2", "value 2");
 form.add("field 2", "value 3");
 form.add("field 3", 4);  // non-String form values supported as of 5.1.4

 restTemplate.postForLocation("https://example.com/myForm", form);

The following snippet shows how to do a file upload using the "multipart/form-data" content type.

 MultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
 parts.add("field 1", "value 1");
 parts.add("file", new ClassPathResource("myFile.jpg"));

 restTemplate.postForLocation("https://example.com/myFileUpload", parts);

The following snippet shows how to do a file upload using the "multipart/mixed" content type.

 MultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
 parts.add("field 1", "value 1");
 parts.add("file", new ClassPathResource("myFile.jpg"));

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

 restTemplate.postForLocation("https://example.com/myFileUpload",
     new HttpEntity<>(parts, requestHeaders));

The following snippet shows how to do a file upload using the "multipart/related" content type.

 MediaType multipartRelated = new MediaType("multipart", "related");

 restTemplate.getMessageConverters().stream()
     .filter(FormHttpMessageConverter.class::isInstance)
     .map(FormHttpMessageConverter.class::cast)
     .findFirst()
     .orElseThrow(() -> new IllegalStateException("Failed to find FormHttpMessageConverter"))
     .addSupportedMediaTypes(multipartRelated);

 MultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
 parts.add("field 1", "value 1");
 parts.add("file", new ClassPathResource("myFile.jpg"));

 HttpHeaders requestHeaders = new HttpHeaders();
 requestHeaders.setContentType(multipartRelated);

 restTemplate.postForLocation("https://example.com/myFileUpload",
     new HttpEntity<>(parts, requestHeaders));

Miscellaneous

Some methods in this class were inspired by org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity.

Since:
3.0
Author:
Arjen Poutsma, Rossen Stoyanchev, Juergen Hoeller, Sam Brannen
See Also:
  • Field Details

    • DEFAULT_CHARSET

      public static final Charset DEFAULT_CHARSET
      The default charset used by the converter.
  • Constructor Details

    • FormHttpMessageConverter

      public FormHttpMessageConverter()
  • Method Details

    • setSupportedMediaTypes

      public void setSupportedMediaTypes(List<MediaType> supportedMediaTypes)
      Set the list of MediaType objects supported by this converter.
      See Also:
    • addSupportedMediaTypes

      public void addSupportedMediaTypes(MediaType... supportedMediaTypes)
      Add MediaType objects to be supported by this converter.

      The supplied MediaType objects will be appended to the list of supported MediaType objects.

      Parameters:
      supportedMediaTypes - a var-args list of MediaType objects to add
      Since:
      5.2
      See Also:
    • getSupportedMediaTypes

      public List<MediaType> getSupportedMediaTypes()
      Return the list of media types supported by this converter. The list may not apply to every possible target element type and calls to this method should typically be guarded via canWrite(clazz, null. The list may also exclude MIME types supported only for a specific class. Alternatively, use HttpMessageConverter.getSupportedMediaTypes(Class) for a more precise list.
      Specified by:
      getSupportedMediaTypes in interface HttpMessageConverter<MultiValueMap<String,?>>
      Returns:
      the list of supported media types
      See Also:
    • setPartConverters

      public void setPartConverters(List<HttpMessageConverter<?>> partConverters)
      Set the message body converters to use. These converters are used to convert objects to MIME parts.
    • getPartConverters

      public List<HttpMessageConverter<?>> getPartConverters()
      Return the configured converters for MIME parts.
      Since:
      5.3
    • addPartConverter

      public void addPartConverter(HttpMessageConverter<?> partConverter)
      Add a message body converter. Such a converter is used to convert objects to MIME parts.
    • setCharset

      public void setCharset(@Nullable Charset charset)
      Set the default character set to use for reading and writing form data when the request or response Content-Type header does not explicitly specify it.

      As of 4.3, this is also used as the default charset for the conversion of text bodies in a multipart request.

      As of 5.0, this is also used for part headers including Content-Disposition (and its filename parameter) unless (the mutually exclusive) multipartCharset is also set, in which case part headers are encoded as ASCII and filename is encoded with the encoded-word syntax from RFC 2047.

      By default this is set to "UTF-8".

    • setMultipartCharset

      public void setMultipartCharset(Charset charset)
      Set the character set to use when writing multipart data to encode file names. Encoding is based on the encoded-word syntax defined in RFC 2047 and relies on MimeUtility from jakarta.mail.

      As of 5.0 by default part headers, including Content-Disposition (and its filename parameter) will be encoded based on the setting of setCharset(Charset) or UTF-8 by default.

      Since:
      4.1.1
      See Also:
    • canRead

      public boolean canRead(Class<?> clazz, @Nullable MediaType mediaType)
      Description copied from interface: HttpMessageConverter
      Indicates whether the given class can be read by this converter.
      Specified by:
      canRead in interface HttpMessageConverter<MultiValueMap<String,?>>
      Parameters:
      clazz - the class to test for readability
      mediaType - the media type to read (can be null if not specified); typically the value of a Content-Type header.
      Returns:
      true if readable; false otherwise
    • canWrite

      public boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType)
      Description copied from interface: HttpMessageConverter
      Indicates whether the given class can be written by this converter.
      Specified by:
      canWrite in interface HttpMessageConverter<MultiValueMap<String,?>>
      Parameters:
      clazz - the class to test for writability
      mediaType - the media type to write (can be null if not specified); typically the value of an Accept header.
      Returns:
      true if writable; false otherwise
    • read

      Description copied from interface: HttpMessageConverter
      Read an object of the given type from the given input message, and returns it.
      Specified by:
      read in interface HttpMessageConverter<MultiValueMap<String,?>>
      Parameters:
      clazz - the type of object to return. This type must have previously been passed to the canRead method of this interface, which must have returned true.
      inputMessage - the HTTP input message to read from
      Returns:
      the converted object
      Throws:
      IOException - in case of I/O errors
      HttpMessageNotReadableException - in case of conversion errors
    • write

      public void write(MultiValueMap<String,?> map, @Nullable MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException
      Description copied from interface: HttpMessageConverter
      Write an given object to the given output message.
      Specified by:
      write in interface HttpMessageConverter<MultiValueMap<String,?>>
      Parameters:
      map - the object to write to the output message. The type of this object must have previously been passed to the canWrite method of this interface, which must have returned true.
      contentType - the content type to use when writing. May be null to indicate that the default content type of the converter must be used. If not null, this media type must have previously been passed to the canWrite method of this interface, which must have returned true.
      outputMessage - the message to write to
      Throws:
      IOException - in case of I/O errors
      HttpMessageNotWritableException - in case of conversion errors
    • getFormContentType

      protected MediaType getFormContentType(@Nullable MediaType contentType)
      Return the content type used to write forms, given the preferred content type. By default, this method returns the given content type, but adds the charset if it does not have one. If contentType is null, application/x-www-form-urlencoded; charset=UTF-8 is returned.

      Subclasses can override this method to change this behavior.

      Parameters:
      contentType - the preferred content type (can be null)
      Returns:
      the content type to be used
      Since:
      5.2.2
    • serializeForm

      protected String serializeForm(MultiValueMap<String,Object> formData, Charset charset)
    • generateMultipartBoundary

      protected byte[] generateMultipartBoundary()
      Generate a multipart boundary.

      This implementation delegates to MimeTypeUtils.generateMultipartBoundary().

    • getHttpEntity

      protected HttpEntity<?> getHttpEntity(Object part)
      Return an HttpEntity for the given part Object.
      Parameters:
      part - the part to return an HttpEntity for
      Returns:
      the part Object itself it is an HttpEntity, or a newly built HttpEntity wrapper for that part
    • getFilename

      @Nullable protected String getFilename(Object part)
      Return the filename of the given multipart part. This value will be used for the Content-Disposition header.

      The default implementation returns Resource.getFilename() if the part is a Resource, and null in other cases. Can be overridden in subclasses.

      Parameters:
      part - the part to determine the file name for
      Returns:
      the filename, or null if not known