I'm trying to build a controller with PatchMapping
to handle multipart/form-data
.
POST
with multipart/form-data
is working fine. But PATCH
request always throws MultipartException
even though the request I'm sending from postman is absolutely correct. I even tried to send PATCH
without file1
and file2
but still getting same issue.
build.gradle
plugins and dependencies
plugins {
id 'org.springframework.boot' version '2.4.5'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
id 'project-report'
id 'jacoco'
id "org.sonarqube" version '3.3'
id 'net.linguica.maven-settings' version '0.5'
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-aop'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'io.micrometer:micrometer-registry-prometheus'
implementation 'com.google.guava:guava:30.0-jre'
implementation 'org.apache.commons:commons-lang3:3.0'
implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'
implementation 'org.springframework.boot:spring-boot-starter-data-mongodb-reactive'
implementation 'com.github.java-json-tools:json-patch:1.13'
implementation 'net.logstash.logback:logstash-logback-encoder:6.6'
implementation group: 'javax.persistence', name: 'javax.persistence-api', version: '2.2'
implementation 'commons-io:commons-io:1.4'
implementation 'commons-beanutils:commons-beanutils:1.9.4'
implementation 'org.apache.httpcomponents:httpclient:4.4.1'
implementation group: 'commons-fileupload', name: 'commons-fileupload', version: '1.4'
}
curl
curl --location --request PATCH 'http://localhost:8443/employeeapp/v1/employees/4002494283' \
--header 'X-GP-Request-Id: $3bfc8e1c-ec2f-4d4b-8a82-f856037cb1e4' \
--header 'Content-Type: multipart/form-data' \
--form 'update_request="{
\"emp_attributes\":[
{
\"name\":\"dept_id\",
\"value\":\"123\"
},
{
\"name\":\"email\",
\"value\":\"[email protected]\"
}
],
\"user_name\":\"[email protected]\"
}"' \
--form 'file1=@"/file1.txt"' \
--form 'file2=@"/file2.txt"'
Main.java
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
@Bean(name = "multipartResolver")
public CommonsMultipartResolver multipartResolver() {
return new CommonsMultipartResolver();
}
}
controller
@PatchMapping(path="/" EMP_ID_REGEX, consumes = {MediaType.MULTIPART_FORM_DATA_VALUE}, produces = {MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<Employee> updateEmployee(@RequestHeader("X-GP-Request-Id") String UUID,
@PathVariable ("empId") String empId,
@Valid @RequestPart("update_request") UpdateRequest updateRequest,
@RequestPart(value ="file1", required = false) MultipartFile file1,
@RequestPart(value ="file2", required = false) MultipartFile file2
) throws Exception {}
I don't get why POST
with the same data is working but PATCH
is not working. Am I missing something at application level?
CodePudding user response:
You have need to modify your curl request.
curl --location --request PATCH 'http://localhost:8443/employeeapp/v1/employees/4002494283' \
--header 'X-GP-Request-Id: $3bfc8e1c-ec2f-4d4b-8a82-f856037cb1e4' \
--header 'Content-Type: multipart/form-data' \
--form 'update_request="{
\"emp_attributes\":[
{
\"name\":\"dept_id\",
\"value\":\"123\"
},
{
\"name\":\"email\",
\"value\":\"[email protected]\"
}
],
\"user_name\":\"[email protected]\"
}";type=application/json' \
--form 'file1=@"/file1.txt"' \
--form 'file2=@"/file2.txt"'
It works for me. Issue with your curl request controller not able to resolve json request part body.
Also For me without type=application/json
post is also not working.
CodePudding user response:
Class CommonsMultipartResolver
has an isMultipart
method which determines whether the request contains multipart content. This method returns false
if the request is not a POST
.
Here's its code:
if (!POST_METHOD.equalsIgnoreCase(request.getMethod())) {
return false;
}
return FileUploadBase.isMultipartContent(new ServletRequestContext(request));
All you need to do is remove first check. You can do this by overriding the method when creating the bean:
@Bean(name = "multipartResolver")
public CommonsMultipartResolver multipartResolver() {
return new CommonsMultipartResolver() {
@Override
public boolean isMultipart(HttpServletRequest request) {
return FileUploadBase.isMultipartContent(new ServletRequestContext(request));
}
};
}
PS: If you do not replace multipartResolver
with your own, then the standard StandardServletMultipartResolver
will work with both POST and PATCH requests