In my previous tutorial I had shown Spring MVC Single File Upload Example. In this tutorial I am going to show an example on how to upload multiple files using Spring MVC. I am going to use Spring Boot framework to upload multiple files.
I am using Thymeleaf as a template file for displaying UI (User Interface). I have put basic validation for the file upload form. If you do not select any file for upload then you will see an error message.
Prerequisites
Java at least 8, Spring Boot 2.3.3, Gradle 6.5.1, Maven 3.6.3
Project Setup
Either create gradle or maven based project in your favorite IDE or tool. The name of the project is spring-mvc-multiple-files-upload.
If you creating gradle based project then you can use below build.gradle script:
buildscript {
ext {
springBootVersion = '2.3.3.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
plugins {
id 'java-library'
id 'org.springframework.boot' version "${springBootVersion}"
}
sourceCompatibility = 12
targetCompatibility = 12
repositories {
mavenCentral()
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web:${springBootVersion}")
implementation("org.springframework.boot:spring-boot-starter-thymeleaf:${springBootVersion}")
}
If you are creating maven based project then you can use below pom.xml file:
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.roytuts</groupId>
<artifactId>spring-mvc-multiple-files-upload</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.3.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</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-thymeleaf</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>at least 8</source>
<target>at least 8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Spring Controller
Spring controller is responsible for handling any request and response for the clients. Here I have defined two endpoints in the following Spring controller class.
The root path (“/”) displays the file upload form or page where a browse button is given for selecting multiple files.
Other endpoint path (“/upload/files”) upload the selected files into server location.
package com.roytuts.spring.mvc.multiple.files.upload;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
@Controller
public class FileUploadController {
private final String UPLOAD_FOLDER = "/upload";
@GetMapping("/")
public String uploadFiles() {
return "uploadfiles";
}
@PostMapping("upload/files")
public String handleFilesUpload(@RequestParam("files") MultipartFile files[], Model map) {
StringBuilder sb = new StringBuilder();
for (MultipartFile file : files) {
if (!file.isEmpty()) {
try {
if (!Files.exists(Paths.get(UPLOAD_FOLDER))) {
try {
Files.createDirectories(Paths.get(UPLOAD_FOLDER));
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
Files.copy(file.getInputStream(), Paths.get(UPLOAD_FOLDER, file.getOriginalFilename()));
sb.append("You successfully uploaded " + file.getOriginalFilename() + "!\n");
map.addAttribute("msg", sb.toString());
} catch (IOException | RuntimeException e) {
sb.append("Failued to upload " + (file != null ? file.getOriginalFilename() : "") + " => "
+ e.getMessage() + String.valueOf(e) + "\n");
map.addAttribute("msg", sb.toString());
}
} else {
sb.append("Failed to upload file\n");
map.addAttribute("msg", sb.toString());
}
}
return "uploadfiles";
}
}
View File
The view file or Thymeleaf template file is kept under the classpath directory src/main/resources/templates.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Spring MVC Multiple Files Upload Example</title>
</head>
<body>
<h2>Spring MVC Multiple Files Upload Example</h2>
<div th:if="${msg != null}" th:text="${msg}"></div>
<form name='upload_files' enctype="multipart/form-data"
th:action="@{/upload/files}" method='POST'>
Select Files: <input type="file" name="files" multiple="multiple" /> <br />
<br /> <input value="Upload" type="submit" />
</form>
</body>
</html>
Main Class
A class with @SpringBootApplication
and main method is enough to deploy the application into embedded Tomcat server.
package com.roytuts.spring.mvc.multiple.files.upload;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringMvcMultipleFilesUploadApp {
public static void main(String[] args) {
SpringApplication.run(SpringMvcMultipleFilesUploadApp.class, args);
}
}
Testing the Application
When you hit the URL http://localhost:8080/ in the browser, you will see below page:

If you try to click on Upload button without selecting any file:

When files successfully uploaded to the destination directory:

I have uploaded three different files and after successful upload their names are shown on the UI.
Source Code
Thanks for reading.