Guide to use multipart/form-data
To use multipart/form-data, the request needs to be structured to send different parts of the body separately or all the parts together. In Spring Boot. multipart requests are used for sending data of many different types separated by a boundary as part of a single HTTP request.
For different languages/frameworks the structuring process may differ and may depend on the libraries being used to create the request.
But generally to structure a request, the parts need to be set as per requirement and proper boundaries are needed to be set in between them.
Boundaries in multipart/form-data
A multipart request can contains fields of different types, these are separated by boundaries. Most libraries set these boundaries automatically but in come scenarios this process needs to be carried out manually.
This helps the server differentiate the different parts and parse them as per requirement but if done manually it must be unique within the request to avoid conflicts with the actual data.
Sending individual parts in a request
Using a high level library
High level libraries likeOkHttp
handlemultipart/form-data
request automatically and can send all the parts or individual parts by handling the boundaries.Sending single part using a library like
OkHttp
can be done as follows:val requestBody = MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart("text", "sample data string") .build()
Using low level libraries
To send individual parts in low level libraries where headers are not managed, the boundaries may needed to be set manually in code, an example is as follows:Define a unique boundary string.
String myCustomBoundary = "----myCustomBoundary";
Then the boundary can be added to the
Content-Type
header as follows:HttpURLConnection httpConnection= (HttpURLConnection) new URL("sample-url").openConnection(); connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + myCustomBoundary);
Alternatively one can insert the boundary string between the different parts of the request body
The boundary string must be a unique identifier
The boundary string must begin with 2 hyphens
--
at the start and towards the end.
Sending multiple parts in same request
Multiple parts are usually handled automatically in high level libraries like OkHttp
, where the boundaries are set automatically as follows:
Once donr the request body can be sent as part of request
Sending of multiple parts using low level libraries where boundaries are not handled is explained here.
Content Disposition Header
This is an important header and must be included as part of each part of a multipart request, this is because the Content-Disposition
header explains how data needs to be processed.
This header helps the server identify whether the part of request is a form or file field. Which can then be used to associate the parts to expected fields.
Content-Disposition for form data:
Content-Disposition for file data:
Here, the name
is the field name expected by server, and filename
is used for files to let the server know with a default name.
Content-Type Header
Specifying Content-Type
header for individul fields is optional but can be helpful when dealing with files or sending the data individually. And doing so ensures each part is interpreted correctly. Without explicit content type header, especially for non-text files, the server might misinterpret or improperly parse file data.
For text fields the
Content-Type
header istext/plain
, and for specific types of data like JSON it isapplication/json
, for other data types like XML this header can be set accordingly. If this header is not provided, servers default totext/plain
, but setting it explicitly can help.For files, specifying the
Content-Type
helps the server identify the file’s MIME type, for example:Images are identified using
image/jpeg
ZIP files are identified using
application/zip
Data Encoding
This applies to text or string fields epecially for non ASCII languages containing special characters. For these fields UTF-8
encoding is provided as part of header, because UTF-8 is most commonly used and supports almost all characters. Without specifying the character encoding, special characters might get misinterpreted.
String Length
Some servers have a default limit on the length of data sent via text fields in a multipart request. For such scenarios it is suggested to chunk large text into separate parts or fields.
Apache HttpClient in Java or OkHttp in Kotlin support multipart streaming, where data is sent in chunks without loading the entire text into memory at once.
Some other considerations when dealing with large strings of data are:
URL encoding: sometimes it is recommended to URL-encode text fields if they have special characters like hyphens, ampersands, etc as they can interfere with boundary parsing.
Whitespace and Line breaks: Leading or trailing whitespaces or line breaks may impact parsing of text fields as servers automatically trim these characters. Adding
\r\n
instead enures clarity and proper separation.MIME for structured data: When using structured data like JSON or XML use
Content-Type
appropriately, for exampleapplication/json
andapplication/xml
respectively, as the servers default totext/plain
in most cases.