Keywords: Spring | MVC | Multipart | JSON | File_Upload
Abstract: This article provides a comprehensive guide on handling mixed multipart requests containing both JSON data and files in the Spring MVC framework. It covers backend implementation using @RequestPart annotation, frontend integration with FormData API, and best practices to avoid common pitfalls such as MissingServletRequestPartException.
Overview of the Problem
In web development, there is often a need to upload files along with metadata, such as JSON-formatted configuration data. Spring MVC provides the @RequestPart annotation to handle such mixed requests.
Backend Implementation
In a Spring controller, the @RequestPart annotation can be used to bind request parts to objects. Example code:
@RequestMapping(value = "/executesampleservice", method = RequestMethod.POST, consumes = {"multipart/form-data"})
@ResponseBody
public boolean executeSampleService(
@RequestPart("properties") @Valid ConnectionProperties properties,
@RequestPart("file") @Valid @NotNull @NotBlank MultipartFile file) {
return projectService.executeSampleService(properties, file);
}
Here, the properties part is treated as JSON data, which Spring automatically deserializes into the ConnectionProperties class. Note that using consumes = {"multipart/form-data"} ensures only multipart requests are accepted.
Frontend Implementation
On the frontend, use the JavaScript FormData API to construct the request. Key steps:
- Create a
FormDataobject. - Append the file part, e.g., via a file input element or direct file object.
- Append JSON data as a Blob, setting
Content-Typetoapplication/jsonto preserve data type. - When sending the request, set
Content-Typetoundefinedto allow the browser to handle boundaries automatically.
formData = new FormData();
formData.append("file", document.forms[formName].file.files[0]);
formData.append('properties', new Blob([JSON.stringify({
"name": "root",
"password": "root"
})], {
type: "application/json"
}));
Request Details
Properly setting Content-Type is crucial. If manually set to multipart/form-data, the browser may fail to generate boundaries correctly, leading to errors like MissingServletRequestPartException. Thus, it is recommended to set Content-Type to undefined. An example request payload:
Accept:application/json, text/plain, */*
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryEBoJzS3HQ4PgE1QB
------WebKitFormBoundaryvijcWI2ZrZQ8xEBN
Content-Disposition: form-data; name="file"; filename="myfile.txt"
Content-Type: application/txt
------WebKitFormBoundaryvijcWI2ZrZQ8xEBN
Content-Disposition: form-data; name="properties"; filename="blob"
Content-Type: application/json
------WebKitFormBoundaryvijcWI2ZrZQ8xEBN--
Best Practices
Ensure consistency between frontend and backend: use @RequestPart for binding on the backend and FormData for request construction on the frontend. Validate input data, e.g., with JSR-303 annotations like @Valid and @NotNull. Additionally, consider error handling and logging to improve robustness.
Conclusion
By combining the @RequestPart annotation with the FormData API, mixed multipart requests in Spring MVC can be handled efficiently. This approach supports flexible data structures, such as JSON with file uploads, and is suitable for various web application scenarios.