Best Practices for Handling Multipart and JSON Mixed Uploads in Spring Boot

Dec 02, 2025 · Programming · 13 views · 7.8

Keywords: Spring Boot | Multipart | JSON | FormData | @ModelAttribute

Abstract: This article discusses common issues and solutions for uploading multipart files and JSON data together in Spring Boot applications, focusing on using @ModelAttribute and FormData for seamless integration to avoid content type mismatches.

Introduction

In modern web applications, handling file uploads alongside structured data like JSON is a frequent requirement. When using Spring Boot for backend development, a common challenge arises when clients send <code>multipart/form-data</code> requests that mix files and JSON, leading to exceptions such as <code>HttpMediaTypeNotSupportedException</code>.

Problem Analysis

The root cause of this issue is the mismatch between the expected content type in the Spring controller and the actual request. In the provided example, the controller uses <code>@RequestBody</code> to bind JSON data, but the frontend sends a <code>multipart/form-data</code> request, which includes both form fields and a file.

Solution with @ModelAttribute and FormData

To seamlessly handle mixed content, the recommended approach is to use <code>@ModelAttribute</code> in Spring Boot and <code>FormData</code> on the frontend. This allows automatic data binding without manual content type settings.

On the frontend, in frameworks like React or vanilla JavaScript, create a <code>FormData</code> object and append all data, including files. Avoid setting the <code>Content-Type</code> header; let the browser automatically set it to <code>multipart/form-data</code>.

// Example in React
_onSubmit = values => {
    let formData = new FormData();
    formData.append('title', values.title);
    formData.append('description', values.description);
    formData.append('amount', values.amount);
    formData.append('image', values.image[0]);
    axios.post(ENDPOINT, formData); // No custom headers for Content-Type
};

In the Spring Boot controller, define a Data Transfer Object (DTO) that matches the form fields and use <code>@ModelAttribute</code> with the <code>consumes</code> attribute set to <code>{"multipart/form-data"}</code>.

@PostMapping(path = "/{groupId}", consumes = {"multipart/form-data"})
public ExpenseSnippetGetDto create(@ModelAttribute ExpensePostDto expenseDto, @PathVariable long groupId, Principal principal) {
    // Process the DTO, which includes fields like title, description, amount, and a MultipartFile image
    // Example DTO:
    // public class ExpensePostDto {
    //     private String title;
    //     private String description;
    //     private BigDecimal amount;
    //     private MultipartFile image;
    // }
    // Ensure getters and setters are present
    return expenseService.createExpense(expenseDto, groupId, principal);
}

Alternative Method Using @RequestPart

For more control, <code>@RequestPart</code> can be used to bind specific parts of the multipart request. This is useful when JSON data needs to be validated separately.

@PostMapping(value = "/upload", consumes = {"multipart/form-data"})
public ResponseEntity<String> upload(@RequestPart("user") @Valid User user, @RequestPart("file") MultipartFile file) {
    // User is a POJO with fields like firstName and lastName, validated using annotations
    // File is handled separately
    System.out.println("User: " + user);
    System.out.println("File: " + file.getOriginalFilename());
    return ResponseEntity.ok("Upload successful");
}

On the frontend, when using <code>@RequestPart</code>, the JSON part should be appended as a Blob with the content type set to <code>application/json</code>.

// Example in JavaScript
formData.append('user', new Blob([JSON.stringify({
    "firstName": "John",
    "lastName": "Doe"
})], { type: "application/json" }));
formData.append('file', document.querySelector('input[type="file"]').files[0]);

Best Practices and Considerations

When implementing such solutions, ensure that the field names in the DTO match the keys used in <code>FormData.append()</code>. Use validation annotations like <code>@NotNull</code> or <code>@NotBlank</code> for robust error handling. For file uploads, consider security aspects such as file size limits, MIME type checking, and storage strategies to prevent vulnerabilities.

Conclusion

Handling multipart and JSON mixed uploads in Spring Boot can be efficiently achieved by leveraging <code>@ModelAttribute</code> with <code>FormData</code>, which simplifies data binding and avoids content type issues. For advanced scenarios, <code>@RequestPart</code> offers finer-grained control. By following these practices, developers can build robust and scalable APIs for modern web applications.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.