I’m working on a Spring Boot application where I need to handle file uploads. I have a default method that currently accepts a single MultipartFile, and I want to modify it to accept an array of MultipartFile. Here's my current code:
import .springframework.http.HttpStatus;
import .springframework.http.ResponseEntity;
import .springframework.web.multipart.MultipartFile;
// Override this method
default ResponseEntity<Void> uploadFiles(String msName, MultipartFile files) {
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
}
I want to change this method to accept an array of MultipartFile like this:
default ResponseEntity<Void> uploadFiles(String msName, MultipartFile[] files) {
// Implementation to handle multiple files
}
Swagger file which help to generate code in target folder
openapi: 3.0.1
info:
title: Upload API
description: API to upload multiple files with an associated microservice name.
version: 1.0.0
paths:
/upload:
post:
summary: Upload multiple files with a microservice name
operationId: uploadFiles
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
properties:
ms_name:
type: string
description: Name of the microservice
files:
type: array
items:
type: string
format: binary
description: Array of files to upload
responses:
"200":
description: Files uploaded successfully
"400":
description: Bad request
"500":
description: Internal server error
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns=".0.0"
xmlns:xsi=";
xsi:schemaLocation=".0.0 .0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.builder.ms</groupId>
<artifactId>parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../parent</relativePath>
</parent>
<groupId>com.builder.api</groupId>
<artifactId>api</artifactId>
<packaging>jar</packaging>
<properties>
<java.version>17</java.version>
<resource.dir>${project.basedir}/arc/main/resources</resource.dir>
<external.api.dir>${resource.dir}/swagger/external-api</external.api.dir>
<api-package>com.vishal.nikita.ms.productorder.resources.interfaces</api-package>
<model-package>com.vishal.nikita.ms.productorder.resources.models</model-package>
<adoc.file>product-management</adoc.file>
<generated.asciidoc.directory>${project.build.directory}/asciidoc/generated</generated.asciidoc.directory>
<asciidoctor.html.output.directory>${project.build.directory}/asciidoc/html</asciidoctor.html.output.directory>
<asciidoctor.input.directory>${project.basedir}/src/main/resources/docs</asciidoctor.input.directory>
</properties>
<dependencies>
<!-- Jakarta Dependencies -->
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
<version>3.0.2</version>
</dependency>
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>jakarta.inject</groupId>
<artifactId>jakarta.inject-api</artifactId>
<version>2.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>5.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jakarta.ws.rs</groupId>
<artifactId>jakarta.ws.rs-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- Spring Boot Dependencies -->
<dependency>
<groupId>.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
</dependency>
<!-- Testing Dependencies -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
</dependency>
<dependency>
<groupId>.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
</dependency>
<!-- OpenAPI/Swagger Dependencies -->
<dependency>
<groupId>.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>.openapitools</groupId>
<artifactId>jackson-databind-nullable</artifactId>
<version>0.2.6</version>
</dependency>
<dependency>
<groupId>.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>2.0</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>${project.build.directory}/generated-sources/src/main/resources</directory>
</resource>
<resource>
<directory>${resource.dir}</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>7.1.0</version>
<executions>
<execution>
<id>generate-api</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>${project.basedir}/src/main/resources/swaggerapi.yaml</inputSpec>
<generatorName>spring</generatorName>
<output>${project.build.directory}/generated-sources/api</output>
<apiPackage>com.builder.api</apiPackage>
<modelPackage>com.builder.model</modelPackage>
<invokerPackage>com.builder.client</invokerPackage>
<configOptions>
<interfaceOnly>true</interfaceOnly>
<useJakartaEe>true</useJakartaEe>
<useSpringBoot3>true</useSpringBoot3>
<delegatePattern>true</delegatePattern>
</configOptions>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
What I've Tried:
- I updated the method signature to accept MultipartFile[] files.
- I added a check to ensure the files array is not null or empty.
- I iterated over the array to process each file.
Here's my updated code:
default ResponseEntity<Void> uploadFiles(String msName, MultipartFile[] files) {
if (files == null || files.length == 0) {
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
for (MultipartFile file : files) {
if (!file.isEmpty()) {
// Process each file
}
}
return new ResponseEntity<>(HttpStatus.OK);
}
My questions:
- Is this the correct way to handle an array of MultipartFile in Spring Boot?
- How can I ensure that the files are properly validated (e.g., file size, file type)?
- Are there any best practices or potential pitfalls I should be aware of when handling multiple file uploads?
Additional context:
- I'm using Spring Boot 3.x.
- The files are being uploaded via a REST API endpoint.
I want to ensure the solution is scalable and handles edge cases (e.g., large files, invalid file types).
I'm using OpenAPI Tools, which automatically generates the interface. Even though I made changes in the target directory (UploadApi), they get removed whenever I perform a clean install because OpenAPI Tools regenerates the interface. Locally, I can modify it, but when deploying in real-time, Jenkins creates a new target directory, causing it to fail. I need a solution where, after performing a clean install, the following code is generated automatically.
I’m working on a Spring Boot application where I need to handle file uploads. I have a default method that currently accepts a single MultipartFile, and I want to modify it to accept an array of MultipartFile. Here's my current code:
import .springframework.http.HttpStatus;
import .springframework.http.ResponseEntity;
import .springframework.web.multipart.MultipartFile;
// Override this method
default ResponseEntity<Void> uploadFiles(String msName, MultipartFile files) {
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
}
I want to change this method to accept an array of MultipartFile like this:
default ResponseEntity<Void> uploadFiles(String msName, MultipartFile[] files) {
// Implementation to handle multiple files
}
Swagger file which help to generate code in target folder
openapi: 3.0.1
info:
title: Upload API
description: API to upload multiple files with an associated microservice name.
version: 1.0.0
paths:
/upload:
post:
summary: Upload multiple files with a microservice name
operationId: uploadFiles
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
properties:
ms_name:
type: string
description: Name of the microservice
files:
type: array
items:
type: string
format: binary
description: Array of files to upload
responses:
"200":
description: Files uploaded successfully
"400":
description: Bad request
"500":
description: Internal server error
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache./POM/4.0.0"
xmlns:xsi="http://www.w3./2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache./POM/4.0.0 http://maven.apache./xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.builder.ms</groupId>
<artifactId>parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../parent</relativePath>
</parent>
<groupId>com.builder.api</groupId>
<artifactId>api</artifactId>
<packaging>jar</packaging>
<properties>
<java.version>17</java.version>
<resource.dir>${project.basedir}/arc/main/resources</resource.dir>
<external.api.dir>${resource.dir}/swagger/external-api</external.api.dir>
<api-package>com.vishal.nikita.ms.productorder.resources.interfaces</api-package>
<model-package>com.vishal.nikita.ms.productorder.resources.models</model-package>
<adoc.file>product-management</adoc.file>
<generated.asciidoc.directory>${project.build.directory}/asciidoc/generated</generated.asciidoc.directory>
<asciidoctor.html.output.directory>${project.build.directory}/asciidoc/html</asciidoctor.html.output.directory>
<asciidoctor.input.directory>${project.basedir}/src/main/resources/docs</asciidoctor.input.directory>
</properties>
<dependencies>
<!-- Jakarta Dependencies -->
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
<version>3.0.2</version>
</dependency>
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>jakarta.inject</groupId>
<artifactId>jakarta.inject-api</artifactId>
<version>2.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>5.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jakarta.ws.rs</groupId>
<artifactId>jakarta.ws.rs-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- Spring Boot Dependencies -->
<dependency>
<groupId>.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
</dependency>
<!-- Testing Dependencies -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
</dependency>
<dependency>
<groupId>.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
</dependency>
<!-- OpenAPI/Swagger Dependencies -->
<dependency>
<groupId>.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>.openapitools</groupId>
<artifactId>jackson-databind-nullable</artifactId>
<version>0.2.6</version>
</dependency>
<dependency>
<groupId>.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>2.0</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>${project.build.directory}/generated-sources/src/main/resources</directory>
</resource>
<resource>
<directory>${resource.dir}</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>7.1.0</version>
<executions>
<execution>
<id>generate-api</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>${project.basedir}/src/main/resources/swaggerapi.yaml</inputSpec>
<generatorName>spring</generatorName>
<output>${project.build.directory}/generated-sources/api</output>
<apiPackage>com.builder.api</apiPackage>
<modelPackage>com.builder.model</modelPackage>
<invokerPackage>com.builder.client</invokerPackage>
<configOptions>
<interfaceOnly>true</interfaceOnly>
<useJakartaEe>true</useJakartaEe>
<useSpringBoot3>true</useSpringBoot3>
<delegatePattern>true</delegatePattern>
</configOptions>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
What I've Tried:
- I updated the method signature to accept MultipartFile[] files.
- I added a check to ensure the files array is not null or empty.
- I iterated over the array to process each file.
Here's my updated code:
default ResponseEntity<Void> uploadFiles(String msName, MultipartFile[] files) {
if (files == null || files.length == 0) {
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
for (MultipartFile file : files) {
if (!file.isEmpty()) {
// Process each file
}
}
return new ResponseEntity<>(HttpStatus.OK);
}
My questions:
- Is this the correct way to handle an array of MultipartFile in Spring Boot?
- How can I ensure that the files are properly validated (e.g., file size, file type)?
- Are there any best practices or potential pitfalls I should be aware of when handling multiple file uploads?
Additional context:
- I'm using Spring Boot 3.x.
- The files are being uploaded via a REST API endpoint.
I want to ensure the solution is scalable and handles edge cases (e.g., large files, invalid file types).
I'm using OpenAPI Tools, which automatically generates the interface. Even though I made changes in the target directory (UploadApi), they get removed whenever I perform a clean install because OpenAPI Tools regenerates the interface. Locally, I can modify it, but when deploying in real-time, Jenkins creates a new target directory, causing it to fail. I need a solution where, after performing a clean install, the following code is generated automatically.
Share edited Mar 8 at 12:33 Mark Rotteveel 110k229 gold badges156 silver badges224 bronze badges asked Mar 6 at 21:01 Vishal ThakurVishal Thakur 11 bronze badge1 Answer
Reset to default 0API
@PostMapping("/upload")
public ResponseEntity<Void> uploadFiles(
@RequestParam String msName,
@RequestParam("files") MultipartFile[] files // The parameter name must be consistent with the front end
) {
if (files != null && files.length > 0) {
for (MultipartFile file : files) {
// Process each file
if (!file.isEmpty()) {
String fileName = file.getOriginalFilename();
System.out.println(fileName);
System.out.println(file.getSize());
System.out.println(file.getContentType());
// Save files or other operations
}
}
return new ResponseEntity<>(HttpStatus.OK);
} else {
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
}
HTML
<form method="POST" action="http://localhost:7182/file/upload" enctype="multipart/form-data">
<input type="text" name="msName" />
<input type="file" name="files" multiple> <!-- Key: multiple attribute -->
<button type="submit">上传</button>
</form>
You can try this demo, it seems to work, and you can also verify the file type and size.