Home > database >  Spring Boot - multipart/form-data POST request is working but multipart/form-data PATCH is not worki
Spring Boot - multipart/form-data POST request is working but multipart/form-data PATCH is not worki

Time:02-02

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

  • Related