Reputation: 11
I want to consume both JSON & files in an API for my spring boot application (using Spring WebFlux). I tried multiple ways as was recommended over the internet (Article1, Article2, Article3), but it's not working for me. The API is not being hit and getting status 415 (Unsupported Media Type) from Postman.
Spring-Boot version : 2.5.3
Spring-Web/Webflux version : 5.3.9
Employee :
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Employee {
private String name;
private int age;
private int mobileNo;
private List<MultipartFile> files;
}
Controller :
@PostMapping(path = "employee", consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.MULTIPART_FORM_DATA_VALUE})
public Mono<Response> processEmployeeDocs(@RequestPart Employee request, @RequestPart List<MultipartFile> files) {
Employee employee = new Employee(request.getName(), request.getAge(), request.getMobileNo(), files);
return employeeService.processDocs(employee);
}
Upvotes: 1
Views: 8790
Reputation: 137
We can achieve this by using RESTEasy's @MultipartForm annotation along with a custom wrapper object:
I've provided the steps that were followed to make this scenario work.
Step 1: Add RESTEasy Multipart Dependency
Make sure you have the RESTEasy multipart provider dependency in your pom.xml:
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-multipart-provider</artifactId>
</dependency>
Step 2: Create the DTO for the JSON Part
Define the class for your JSON object:
public class FirstObject {
private String field1;
private int field2;
// Add Getters and Setters
}
Step 3: Create the Multipart Form Wrapper
Create a class that will hold the multipart form data:
import org.jboss.resteasy.annotations.providers.multipart.MultipartForm;
import org.jboss.resteasy.annotations.providers.multipart.PartType;
import javax.ws.rs.FormParam;
import org.springframework.web.multipart.MultipartFile;
public class MultipleRequestBody {
@FormParam("firstObject")
@PartType("application/json")
private FirstObject firstObject;
@FormParam("file")
@PartType("application/octet-stream")
private byte[] file;
// Add Getters and Setters
}
Note that MultipartFile is a Spring-specific class. Instead, use byte[] / InputStream to handle file uploads in RESTEasy.
Step 4: Create the Controller
Use the @MultipartForm annotation in your controller to handle the multipart request:
import org.jboss.resteasy.annotations.providers.multipart.MultipartForm;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api")
public class MyController {
@PostMapping("/multiple-body")
public ResponseEntity<String> handleMultipleBodies(@MultipartForm MultipleRequestBody request) {
// Process the firstObject (JSON part)
FirstObject firstObject = request.getFirstObject();
String field1 = firstObject.getField1();
int field2 = firstObject.getField2();
// Process the file (file part)
byte[] fileContent = request.getFile();
String fileName = "uploaded_file"; // You can extract the filename if needed
// Perform any necessary processing
// ...
return ResponseEntity.ok("Processed JSON and file successfully");
}
}
Upvotes: 0
Reputation: 181
Instead of using MultipartFile use FilePart to consume multipart content as per the spring docs
Below is the working code snippet
@PostMapping(path = "employees", consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.MULTIPART_FORM_DATA_VALUE})
public Mono<ResponseEntity<Response>> processEmployeeDocs(@RequestPart Employee request, @RequestPart Flux<FilePart> files) {
log.info("processing request {}", request);
return files.flatMap(part -> part.transferTo(Paths.get("temp", File.separator, part.filename())))
.then(employeeService.processDocs(request))
.then(Mono.just(ResponseEntity.ok().build()));
}
The above code will save the files in "temp" directory. You can use those files for processing your logic.
Upvotes: 3