Spring Boot File Upload and Download Rest API Tutorial
Author:
Ramesh Fadatare
π Top 15 Udemy Courses (80-90% Discount): My Udemy Courses - Ramesh Fadatare — All my Udemy courses are real-time and project oriented courses.
▶️ Subscribe to My YouTube Channel (178K+ subscribers): Java Guides on YouTube
▶️ For AI, ChatGPT, Web, Tech, and Generative AI, subscribe to another channel: Ramesh Fadatare on YouTube
In this tutorial, we will learn how to upload and download a file using Spring Boot RESTful API. Uploading and downloading files are very common tasks for which developers need to write code in their applications.
Learn and master in Spring boot at Spring Boot TutorialWe’ll first build the REST APIs for uploading and downloading files, and then test those APIs using Postman.
Let’s get started.
1. Tools and Technologies Used
- Spring Boot - 3+
- JDK - 17 or later
- Spring Framework - 6+
- Maven - 3.2+
- IDE - Eclipse or Spring Tool Suite (STS)
2. Create and Import Spring Boot Project
There are many ways to create a Spring Boot application. The simplest way is to use Spring Initializr at http://start.spring.io/, which is an online Spring Boot application generator.
Let'specify the following details while generating the Spring Boot project using Spring Initializr:
- Project: Select Maven
- Java Version: 17(Default)
- Spring Boot Version: 3.04
- Group: net.javaguides.springboot
- Artifact: springboot-upload-download-file-rest-api-example
- Name: springboot-upload-download-file-rest-api-example
- Description: springboot-upload-download-file-rest-api-example
- Package Name: net.guides.springboot.springbootfileupload
- Packaging: jar (This is the default value)
- Dependencies: Web
Once, all the details are entered, then click on Generate Project button will generate a spring boot project then download it. That’s it! You may now unzip the downloaded application archive and import it into your favorite IDE.
3. Project Directory Structure
Below, the diagram shows a project structure for reference:
4. The pom.xml File
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>net.javaguides.springboot</groupId> <artifactId>springboot-upload-download-file-rest-api-example</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>springboot-upload-download-file-rest-api-example</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.0.4</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>17</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> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
5. Configuring Server and File Storage Properties
Let’s configure our Spring Boot application to enable Multipart file uploads, and define the maximum file size that can be uploaded. We’ll also configure the directory into which all the uploaded files will be stored.
Open the src/main/resources/application.properties file, and add the following properties to it -
## MULTIPART (MultipartProperties) # Enable multipart uploads spring.servlet.multipart.enabled=true # Threshold after which files are written to disk. spring.servlet.multipart.file-size-threshold=2KB # Max file size. spring.servlet.multipart.max-file-size=200MB # Max Request Size spring.servlet.multipart.max-request-size=215MB ## File Storage Properties file.upload-dir=./uploads server.port=8081
6. Automatically binding properties to a POJO class
Spring Boot has an awesome feature called @ConfigurationProperties using which you can automatically bind the properties defined in the application.properties file to a POJO class.
Let’s define a POJO class called FileStorageProperties inside net.javaguides.springboot.fileuploaddownload package to bind all the file storage properties -
package net.javaguides.springboot.fileuploaddownload.property; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Component @ConfigurationProperties(prefix = "file") public class FileStorageProperties { private String uploadDir; public String getUploadDir() { return uploadDir; } public void setUploadDir(String uploadDir) { this.uploadDir = uploadDir; } }
7. Writing APIs for File Upload and Download
File Upload Rest API
Let’s now write the REST APIs for uploading single as well as multiple files. Create a new controller class called FileUploadController inside net.javaguides.springboot.fileuploaddownload.controller package and add the following code to it -
package net.javaguides.springboot.fileuploaddownload.controller; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.support.ServletUriComponentsBuilder; import net.javaguides.springboot.fileuploaddownload.payload.Response; import net.javaguides.springboot.fileuploaddownload.service.FileStorageService; @RestController public class FileUploadController { @Autowired private FileStorageService fileStorageService; @PostMapping("/uploadFile") public Response uploadFile(@RequestParam("file") MultipartFile file) { String fileName = fileStorageService.storeFile(file); String fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath() .path("/downloadFile/") .path(fileName) .toUriString(); return new Response(fileName, fileDownloadUri, file.getContentType(), file.getSize()); } @PostMapping("/uploadMultipleFiles") public List < Response > uploadMultipleFiles(@RequestParam("files") MultipartFile[] files) { return Arrays.asList(files) .stream() .map(file - > uploadFile(file)) .collect(Collectors.toList()); } }
File Download Rest API
Let’s now write the REST API for downloading a file. Create a new controller class called FileDownloadController inside net.javaguides.springboot.fileuploaddownload.controller package and add the following code to it -
package net.javaguides.springboot.fileuploaddownload.controller; import java.io.IOException; import jakarta.servlet.http.HttpServletRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.Resource; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import net.javaguides.springboot.fileuploaddownload.service.FileStorageService; @RestController public class FileDownloadController { private static final Logger logger = LoggerFactory.getLogger(FileDownloadController.class); @Autowired private FileStorageService fileStorageService; @GetMapping("/downloadFile/{fileName:.+}") public ResponseEntity < Resource > downloadFile(@PathVariable String fileName, HttpServletRequest request) { // Load file as Resource Resource resource = fileStorageService.loadFileAsResource(fileName); // Try to determine file's content type String contentType = null; try { contentType = request.getServletContext().getMimeType(resource.getFile().getAbsolutePath()); } catch (IOException ex) { logger.info("Could not determine file type."); } // Fallback to the default content type if type could not be determined if (contentType == null) { contentType = "application/octet-stream"; } return ResponseEntity.ok() .contentType(MediaType.parseMediaType(contentType)) .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"") .body(resource); } }
Response
This Response class is used to return responses from the /uploadFile and /uploadMultipleFiles APIs.
Create a Response class inside net.javaguides.springboot.fileuploaddownload.payload package with the following contents -
public class Response { private String fileName; private String fileDownloadUri; private String fileType; private long size; public Response(String fileName, String fileDownloadUri, String fileType, long size) { this.fileName = fileName; this.fileDownloadUri = fileDownloadUri; this.fileType = fileType; this.size = size; } // Getters and Setters (Omitted for brevity) }
8. Service for Storing Files in the FileSystem and retrieving them
Let’s now write the service for storing files in the file system and retrieving them. Create a new class called FileStorageService.java inside net.javaguides.springboot.fileuploaddownload.service with the following contents -
package net.javaguides.springboot.fileuploaddownload.service; import java.io.IOException; import java.net.MalformedURLException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.Resource; import org.springframework.core.io.UrlResource; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import org.springframework.web.multipart.MultipartFile; import net.javaguides.springboot.fileuploaddownload.exception.FileStorageException; import net.javaguides.springboot.fileuploaddownload.exception.FileNotFoundException; import net.javaguides.springboot.fileuploaddownload.property.FileStorageProperties; @Service public class FileStorageService { private final Path fileStorageLocation; @Autowired public FileStorageService(FileStorageProperties fileStorageProperties) { this.fileStorageLocation = Paths.get(fileStorageProperties.getUploadDir()) .toAbsolutePath().normalize(); try { Files.createDirectories(this.fileStorageLocation); } catch (Exception ex) { throw new FileStorageException("Could not create the directory where the uploaded files will be stored.", ex); } } public String storeFile(MultipartFile file) { // Normalize file name String fileName = StringUtils.cleanPath(file.getOriginalFilename()); try { // Check if the file's name contains invalid characters if (fileName.contains("..")) { throw new FileStorageException("Sorry! Filename contains invalid path sequence " + fileName); } // Copy file to the target location (Replacing existing file with the same name) Path targetLocation = this.fileStorageLocation.resolve(fileName); Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING); return fileName; } catch (IOException ex) { throw new FileStorageException("Could not store file " + fileName + ". Please try again!", ex); } } public Resource loadFileAsResource(String fileName) { try { Path filePath = this.fileStorageLocation.resolve(fileName).normalize(); Resource resource = new UrlResource(filePath.toUri()); if (resource.exists()) { return resource; } else { throw new FileNotFoundException("File not found " + fileName); } } catch (MalformedURLException ex) { throw new FileNotFoundException("File not found " + fileName, ex); } } }
9. Custom Exception Classes
The FileStorageService class throws some exceptions in case of unexpected situations. Following are the definitions of those exception classes (All the exception classes go inside the package net.javaguides.springboot.fileuploaddownload.exception).
FileNotFoundException
package net.javaguides.springboot.fileuploaddownload.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; @ResponseStatus(HttpStatus.NOT_FOUND) public class FileNotFoundException extends RuntimeException { private static final long serialVersionUID = 1 L; public FileNotFoundException(String message) { super(message); } public FileNotFoundException(String message, Throwable cause) { super(message, cause); } }
FileStorageException
package net.javaguides.springboot.fileuploaddownload.exception; public class FileStorageException extends RuntimeException { private static final long serialVersionUID = 1 L; public FileStorageException(String message) { super(message); } public FileStorageException(String message, Throwable cause) { super(message, cause); } }
To know more about exception handling in Spring boot then check out Spring Boot 2 Exception Handling for REST APIs
Note that, we’ve annotated the above exception class with @ResponseStatus(HttpStatus.NOT_FOUND). This ensures that Spring boot responds with a 404 Not Found status when this exception is thrown.
10. Running the Application and Testing the APIs via Postman
We’re done developing our backend APIs. Let’s run the application and test the APIs via Postman. Type the following command from the root directory of the project to run the application -
mvn spring-boot:run
Once started, the application can be accessed at http://localhost:8081
1. Upload File
2. Upload Multiple Files
3. Download the File
Conclusion
That's it. We learned how to upload single as well as multiple files via REST APIs written in Spring Boot. We also learned how to download files in Spring Boot.
I hope the post was helpful to you. You can download the entire code for the project that we built in this article from the GitHub repository.
Learn and master in Spring boot at Spring Boot Tutorial
Related Spring Boot and Microservices Tutorials/Guides:
The Hidden Magic of Spring Boot: Secrets Every Developer Should Know What Happens When You Hit a Spring Boot REST API Endpoint (Behind the Scenes) Spring Boot Exception Handling Build CRUD REST API with Spring Boot, Spring Data JPA, Hibernate, and MySQL Spring Boot DELETE REST API: @DeleteMapping Annotation Spring Boot PUT REST API — @PutMapping Annotation Spring Boot POST REST API Spring Boot GET REST API — @GetMapping Annotation Spring Boot REST API with Request Param | Spring Boot Course Spring Boot REST API with Path Variable — @PathVariable Chapter 13: Understanding @SpringBootApplication Annotation | Spring Boot Course Chapter 5: Create Spring Boot Project and Build Hello World REST API | Spring Boot Course 10 Real-World Spring Boot Architecture Tips Every Developer Should Follow Top 10 Spring Boot Tricks Every Java Developer Should Know Debugging Spring Dependency Injection Issues - Very Important Common Code Smells in Spring Applications — How to Fix Them Spring Boot + OpenAI ChatGPT API Integration Tutorial Spring Boot Course -> New Series on Medium ❤️ Spring Boot Microservices with RabbitMQ Example React JS + Spring Boot Microservices Dockerizing a Spring Boot Application How to Change the Default Port in Spring Boot How to Change Context Path in Spring Boot Top 10 Spring Boot REST API Mistakes and How to Avoid Them (2025 Update) Spring Boot REST API Best Practices Spring Boot Security Database Authentication Example Tutorial Spring Boot Security Form-Based Authentication Spring Boot Security In-Memory Authentication What is Spring Boot Really All About? Why Spring Boot over Spring? Top 10 Spring Boot Key Features That You Should Know Spring vs Spring Boot Setting Up the Development Environment for Spring Boot Spring Boot Auto-Configuration: A Quick Guide Spring Boot Starters Quick Guide to Spring Boot Parent Starter Spring Boot Embedded Servers Spring Boot Thymeleaf Hello World Example Chapter 10: Spring Boot DevTools | Spring Boot Course Chapter 13: Spring Boot REST API That Returns JSON | Spring Boot Course Spring Boot REST API That Returns List of Java Objects in JSON Format Top 10 Spring Boot Mistakes and How to Avoid Them Advanced Spring Boot Concepts that Every Java Developer Should Know What Are Microservices in Spring Boot? Integrating React Frontend with Spring Boot ChatGPT API (Step-by-Step Guide) Build a Chatbot Using Spring Boot, React JS, and ChatGPT API Top 10 Mistakes in Spring Boot Microservices and How to Avoid Them (With Examples) Spring Boot Security Best Practices: Protecting Your Application from Attacks π Dependency Injection in Spring (Explained with Coding Examples) ⚙️ How Spring Container Works Behind the Scenes How Spring Container Works Behind the Scenes (Spring Container Secrets Revealed!) Spring @Component vs @Bean vs @Service vs @Repository Explained How Component Scanning Works Behind the Scenes in Spring How Spring Autowiring Works Internally Top 20 Spring Boot Best Practices for Java Developers Build Spring Boot React Full Stack Project — Todo App [2025 Update] Spring vs Spring MVC vs Spring Boot Spring Boot Best Practices: Use DTOs Instead of Entities in API Responses Spring Boot DTO Tutorial (Using Java record) – Complete CRUD REST API Implementation Spring Boot Architecture: Controller, Service, Repository, Database and Architecture Flow Java Stream filter() Method with Real-World Examples Spring Boot Auto Configuration Explained | How It Works Spring Boot Profiles: How to Manage Environment-Based Configurations Create a Custom Spring Boot Starter | Step-by-Step Guide Spring Boot Starter Modules Explained | Auto-Configuration Guide Deploy Spring Boot Applications with Profile-Based Settings | Step-by-Step Guide Spring Boot Performance Tuning: 10 Best Practices for High Performance Spring Boot @ComponentScan Annotation | Customizing Component Scanning Difference Between @RestController and @RequestMapping in Spring Boot Spring Boot @Cacheable Annotation – Improve Performance with Caching Spring Boot Redis Cache — @Cacheable Complete Guide When to Use @Service, @Repository, @Controller, and @Component Annotations in Spring Boot Why, When, and How to Use @Bean Annotation in Spring Boot App Java Spring Boot vs. Go (Golang) for Backend Development in 2025 Is Autowired Annotation Deprecated in Spring Boot? Everything You Need to Know π« Stop Making These Common Mistakes in Spring Boot Projects Top 10 Mind-Blowing Spring Boot Tricks for Beginners Why Choose Spring Boot Over Spring Framework? | Key Differences and Benefits How to Run a Spring Boot Application | 5 Easy Ways for Developers What is AutoConfiguration in Spring Boot? | Explained with Example Customize Default Configuration in Spring Boot | 5 Proven Ways Chapter 12: Understanding SpringApplication.run() Method Internals | Spring Boot Course What is CommandLineRunner in Spring Boot? How to Create Custom Bean Validation in Spring Boot Can You Build a Non-Web Application with Spring Boot? How to Disable Auto-Configuration in Spring Boot (Step-by-Step Guide) Top 25 Spring Boot Interview Questions and Answers for Beginners How to Use Java Records with Spring Boot Spring Boot Constructor Injection Explained with Step-by-Step Example π« Stop Using @Transactional Everywhere: Understand When You Actually Need It π« Stop Writing Fat Controllers: Follow the Controller-Service-Repository Pattern π« Stop Using Field Injection in Spring Boot: Use Constructor Injection π« Stop Sharing Databases Between Microservices: Use Database Per Service Pattern 10 Java Microservices Best Practices Every Developer Should Follow How to Choose the Right Java Microservices Communication Style (Sync vs Async) How to Implement Event-Driven Communication in Java Microservices (Step-by-Step Guide with Kafka) Stop Building Tight-Coupled Microservices: Aim for Loose Coupling Spring Boot Microservices E-Commerce Project: Step-by-Step Guide Spring Boot Microservices with RabbitMQ Example React JS + Spring Boot Microservices The Ultimate Microservices Roadmap for Beginners: Building Modern Scalable Systems What Are Microservices in Spring Boot? Top 5 Message Brokers Every Developer Should Know Top 10 Spring Cloud Microservices Best Practices [Removed Deprecated Features] Best Tools for Microservices Development in 2025 How to Break a Monolithic Application into Microservices (E-Commerce Use Case) Monoliths Aren’t Dead — Microservices Are Just Overused When to Break a Monolith: A Developer’s Checklist π Java Is Still the King of Microservices — And Here’s the Proof 5 Microservices Design Patterns You Must Know in 2025 Bulkhead Pattern in Microservices — Improve Resilience and Fault Isolation Strangler Fig Pattern in Microservices — Migrate Monolith to Microservices Event Sourcing Pattern in Microservices (With Real-World Example) Circuit Breaker Pattern in Microservices using Spring Boot 3, WebClient and Resilience4j CQRS Pattern in Microservices Aggregator Design Pattern in Microservices — A Complete Guide Database Per Service Pattern in Microservices API Gateway Pattern in Microservices — A Complete Guide Saga Pattern in Microservices: A Step-by-Step Guide Microservices Are a Mess Without These Java Design Patterns️ Java Microservices Interview Questions and Answers for Freshers Top Microservices Interview Questions and Answers for Experienced Professionals Top 10 Microservices Design Pattern Interview Questions and Answers Top Microservices Tricky Interview Questions You Should Know (With Answers) Microservices Best Practices: Building Scalable and Resilient Systems Why Microservices Are the Future of Software Architecture Microservices with Spring Cloud: Simplify Your Architecture Spring Boot and Microservices Roadmap for Beginners [2025 Update] Best Programming Language for Microservices Project Development in 2025 My 50+ Must-Read Microservices Tutorials, Articles and Guides on the Medium Platform
(θΏ½θ¨)
(θΏ½θ¨γγγΎγ§)
Comments
your guide is not up to date compared to github files... mind check that out?
Reply DeleteThanks a lot. I really did benefited from this tutorial.
Reply Deleteand It's work ^^
I've just a little problem at the download GET request,
I always get a 403 Forbidden status (with Postman)
If u have any idea where it can be the problem
*nb I used exactly the same code
I always get a 404 not found status (with Postman)*
DeleteMay be video tutorial will help to your issues.
DeleteCan you please tell how can I integerate it with authentication
Reply DeleteIt would have been great if there were explainatory comments in the code.Would have been even better.
Reply DeletePost a Comment
Leave Comment
[γγ¬γΌγ ]