So I am struggling for a while with sending files and other data to the backend with FormData in the frontend and RequestParam in the backend. I tried so many different things and I have searched so long for solutions and nothing that could fix it. I already made sure that the values are not empty by way of console.logs.
Code:
//Front-End
async addProduct(itemDetails) {
const url = `${this.resourcesUrl}/addProduct`;
const formData = new FormData();
formData.append('name', itemDetails.name);
formData.append('description', itemDetails.description);
formData.append('file1', itemDetails.file1);
formData.append('file2', itemDetails.file2);
const response = await fetch(url, {
method: 'POST',
body: formData,
});
if (response.ok) {
return await response.json();
} else {
const errorResponse = await response.json();
throw new Error(errorResponse.message || 'Failed to add product');
}
}
//Back-End
@PostMapping("/addProduct")
public ResponseEntity<Product> addProduct(
@RequestParam(value = "name") String name,
@RequestParam(value = "description") String description,
@RequestPart(value = "file1") MultipartFile file1,
@RequestPart(value = "file2") MultipartFile file2
) {
try {
String file1Path = fileStorageService.saveFile(name, file1);
String file2Path = fileStorageService.saveFile(name, file2);
Product product = new Product(name, description, file1Path , file2Path);
productRepository.save(product);
return ResponseEntity.ok(product);
} catch (Exception e) {
return ResponseEntity.badRequest().build();
}
}
pom and application.properties:
//relavant part of application.properties
spring.servlet.multipart.enabled=true
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=10MB
//pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.2</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>app</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>app</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>22</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- JWT jackson -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.2</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.2</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.2</version>
<scope>runtime</scope>
</dependency>
<!-- end JWT jackson -->
<dependency>
<groupId>jakarta.persistence</groupId>
<artifactId>jakarta.persistence-api</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
So when I try to add a new product with this values:
name: Test description: Test file1: (file1) file2: (file2)
I get the error: "Required request parameter 'name' for method parameter type String is not present"
The Content-Type of Request Headers in the network tab is application/json but from what I understand is that it should be automatically set to multipart/form-data but it does not do that, even if I explicitly set the Content-Type in the fetch request to multipart/form-data. I think that this is the reason that the passed parameter value is not being recognized.
After having this issue for so long I found out it had to do with a fetch interceptor implementation in my codebase (it sets in each fetch explicitly as Content-Type: application/json) and after removing the explicit Content-Type it worked.
So if you also have this problem you should look if you did set the Content-Type explicitly anywhere in your codebase.