java - How to accept an array of MultipartFile in a Spring Boot method? - Stack Overflow

admin2025-04-18  0

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:

  1. Is this the correct way to handle an array of MultipartFile in Spring Boot?
  2. How can I ensure that the files are properly validated (e.g., file size, file type)?
  3. 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:

  1. Is this the correct way to handle an array of MultipartFile in Spring Boot?
  2. How can I ensure that the files are properly validated (e.g., file size, file type)?
  3. 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 badge
Add a comment  | 

1 Answer 1

Reset to default 0

API

@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.

转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1744949590a276251.html

最新回复(0)