Spring Boot file upload example
This article shows you how to upload a file in Spring Boot web application.
Tools used :
- Spring Boot 1.4.3.RELEASE
- Spring 4.3.5.RELEASE
- Thymeleaf
- Maven
- Embedded Tomcat 8.5.6
1. Project Structure
A standard project structure.
2. Project Dependency
Spring boot dependencies, no need extra library for file upload.
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mkyong</groupId>
<artifactId>spring-boot-file-upload</artifactId>
<packaging>jar</packaging>
<version>1.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.3.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- hot swapping, disable cache for template, enable live reload -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Package as an executable jar/war -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3. File Upload Example
Spring boot file upload, zero configuration.
3.1 In the Controller, maps the uploaded file to MultipartFile
package com.mkyong.controller;
import org.springframework.stereotype.Controller;
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;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@Controller
public class UploadController {
//Save the uploaded file to this folder
private static String UPLOADED_FOLDER = "F://temp//";
@GetMapping("/")
public String index() {
return "upload";
}
@PostMapping("/upload") // //new annotation since 4.3
public String singleFileUpload(@RequestParam("file") MultipartFile file,
RedirectAttributes redirectAttributes) {
if (file.isEmpty()) {
redirectAttributes.addFlashAttribute("message", "Please select a file to upload");
return "redirect:uploadStatus";
}
try {
// Get the file and save it somewhere
byte[] bytes = file.getBytes();
Path path = Paths.get(UPLOADED_FOLDER + file.getOriginalFilename());
Files.write(path, bytes);
redirectAttributes.addFlashAttribute("message",
"You successfully uploaded '" + file.getOriginalFilename() + "'");
} catch (IOException e) {
e.printStackTrace();
}
return "redirect:/uploadStatus";
}
@GetMapping("/uploadStatus")
public String uploadStatus() {
return "uploadStatus";
}
}
3.2 In thymeleaf, just some normal HTML file tags.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<h1>Spring Boot file upload example</h1>
<form method="POST" action="/upload" enctype="multipart/form-data">
<input type="file" name="file" /><br/><br/>
<input type="submit" value="Submit" />
</form>
</body>
</html>
3.3 Another page for upload status
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<body>
<h1>Spring Boot - Upload Status</h1>
<div th:if="${message}">
<h2 th:text="${message}"/>
</div>
</body>
</html>
4. Max upload size exceeded
To handle the max upload size exceeded exception, declares a @ControllerAdvice
and catch the MultipartException
package com.mkyong.controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
@ControllerAdvice
public class GlobalExceptionHandler {
//https://jira.spring.io/browse/SPR-14651
//Spring 4.3.5 supports RedirectAttributes
@ExceptionHandler(MultipartException.class)
public String handleError1(MultipartException e, RedirectAttributes redirectAttributes) {
redirectAttributes.addFlashAttribute("message", e.getCause().getMessage());
return "redirect:/uploadStatus";
}
/* Spring < 4.3.5
@ExceptionHandler(MultipartException.class)
public String handleError2(MultipartException e) {
return "redirect:/errorPage";
}*/
}
5. Tomcat Connection Reset
If you deployed to Tomcat, configure the maxSwallowSize
to avoid this Tomcat connection reset issue. For embedded Tomcat, declares a TomcatEmbeddedServletContainerFactory
like the following :
package com.mkyong;
import org.apache.coyote.http11.AbstractHttp11Protocol;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class SpringBootWebApplication {
private int maxUploadSizeInMb = 10 * 1024 * 1024; // 10 MB
public static void main(String[] args) throws Exception {
SpringApplication.run(SpringBootWebApplication.class, args);
}
//Tomcat large file upload connection reset
//https://mkyong.com/spring/spring-file-upload-and-connection-reset-issue/
@Bean
public TomcatEmbeddedServletContainerFactory tomcatEmbedded() {
TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
tomcat.addConnectorCustomizers((TomcatConnectorCustomizer) connector -> {
if ((connector.getProtocolHandler() instanceof AbstractHttp11Protocol<?>)) {
//-1 means unlimited
((AbstractHttp11Protocol<?>) connector.getProtocolHandler()).setMaxSwallowSize(-1);
}
});
return tomcat;
}
}
6. Multipart File Size
By default, Spring Boot max file upload size is 1MB, you can configure the values via following application properties :
#http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#common-application-properties
#search multipart
spring.http.multipart.max-file-size=10MB
spring.http.multipart.max-request-size=10MB
7. DEMO
Start Spring Boot with the default embedded Tomcat mvn spring-boot:run
.
$ mvn spring-boot:run
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.4.3.RELEASE)
2017-01-21 07:48:53 INFO com.mkyong.SpringBootWebApplication - Starting SpringBootWebApplication on MKYONG-WIN10 with PID 2384 (E:\spring-boot-file-upload\target\classes started by mkyong in E:\spring-boot-file-upload)
2017-01-21 07:48:53 DEBUG com.mkyong.SpringBootWebApplication - Running with Spring Boot v1.4.3.RELEASE, Spring v4.3.5.RELEASE
2017-01-21 07:48:53 INFO com.mkyong.SpringBootWebApplication - No active profile set, falling back to default profiles: default
2017-01-21 07:48:55 INFO com.mkyong.SpringBootWebApplication - Started SpringBootWebApplication in 2.54 seconds (JVM running for 2.924)
7.1 Access http://localhost:8080/
7.2 Select a file and upload it.
7.3 Select a file larger than 10mb, you will visit this page.
Hi, I’m using JPA + Spring Boot. I need to upload one file, save it in disk and save the reference into database. How can I do this?
Good to know about the connection reset issue.
But, note that in SpringBoot 2.0.0 (still in RC1 phase), use class TomcatServletWebServerFactory in place of TomcatEmbeddedServletContainerFactory.
org.springframework.web.multipart.MultipartException: Current request is not a multipart request
This is the error I’m facing while running the applicatin.
You saved my life Man. I have one year experience with Spring Boot Rest and Java, but my memory is like crap, your example works like a charm and thank you very much for putting the import statements, it is a very crucial step.
One suggestion for the people, use Spring Boot Initializer (Search in Google) and import the proyect like Maven in Eclipse.
And by the way (my english sucks), your example maybe save thousands to an hospital, literal.
Thank you.
Hi I have implemented document upload feature in my project in the same manner. All the uploaded documents get saved in the given folder in my server and I am saving the unique reference in the data base for future used and to avoid duplicates. But in my application when ever user uploads new document in the edit old reference will get replaced by new reference in the database. And the old file stays remain in the Folder which is no use. I want to delete the old file as soon as new file uploaded or by using some scheduled job. Can Anybody suggest the best way to remove the unused files using spring boot instead of Java file system. Since the storage is keep filling.
Thanks In advance
Getting FileUploadException: the request was rejected because no multipart boundary was found
when trying from postman
Hello,
Thank you for your articles, I guess I am a regular customer here and I hope that you keep on working with these tutorials which are always concise and informative!
Following your example and then using the example from spring.io (https://spring.io/guides/gs/spring-boot/)
I am wondering about two things – what they have in common is that I would like to do some ‘business-code’ and I hope that you can shed some light.
First of all, if I would like to tamper wit the file ( say it is an xml-file and I would like to transform the numeric values in one column ) and let the user download the tampered file where should I do that ?
the second would be if I save the file, for instance an image, and would like to store the exif-data – where in the code should I pull out that exif data to save in a database ?
best, i
after upload the file getting exception java.nio.file.FileSystemException: F:\temp\test.xlsx: The device is not ready.
Super !
I am using Spring Boot. How can I allow non-executable type files only? Do I need to check file content type and then hard code all executable types to restrict in the controller code? Or is there any other way to mention all unwanted file types? If someone changes the file type what will happen? E.g. test.exe ->test.exe.png , test.exe->test.txt.
You’re awesome mkyong, your examples have been helpful for many years.
how handle multipart/related ?
Hi,
uploading xml file. that file convert xml into java object.
can u give the some examples
Thank you
Excellent content – like usual
why it says “Request method ‘GET’ not supported” when access “http://localhost:8080/”
thanks
Thanks for this awesome post, I have an issue using this on my application : “Current request is not a multipart request”
Any idea about that please ?
look up you upload jsp at enctype=””
Hi,
I am getting simply text as upload when hitting http://localhost:8080/
yes mee too, what is the solution?
when i was using “RestController” i was getting “upload” as response, but when i change to “Controller” in UploadController.java, it is working fine.
could you post the JUNIT test?
how to take the file path from the above example
Hi.
In uploadStatus I would like to show a table with all the info of the uploaded file. In your method singleFileUpload I added a Model to pass the info of file to uploadStatus, but I’m not be able to do it.
Any suggestion?
Thanks for your posts!!!!
Hi,
How can we test this service via rest clieent (preferably postman). Thanks.
How to maintain duplicate files names?
Your awesome…. Your make me happy sleep
how to rename the file to certain pattern .
Upload works fine but how do you display the uploaded image in . Could not get that to work with thymeleaf
Hi, i am having hard times with this issue:
I downloaded your project and ran perfectly first.I tried to create a client using classical http connection and then I tested on my local w?ndows machine and it ran with in two ways. Finally, i wanted to test on linux server and deployed your app on l?nux server. although it ran via browser, i gave java.net.ConnectException: connection timed out when i tried to use my client code. And I also set my client timeout parameter.
I am wondering that if you have any idea about that or not.
Best regards.
Once again thanks for clear example
There’s one mistake, upload.jsp should be upload.html
I can upload, but can’t get image after upload spring boot using angularjs, only after application restart.
Path /resource/img/upload