Spring Boot File Upload and Download REST API
As a developer you may need to work with files and there may be chances that you may need to work with uploading and downloading them. This post explain how you can do with spring boot

In this post, we will see how to upload and download files using Spring Boot as a RESTful web service.
If you want to watch video instead of reading this post, you can see my below video.
Create the project
Create the Spring Boot project using Spring Initializr web tool or using Intellij. I have already added required dependecies for this project, so you can use this link to generate the project and import it into your IDE.
Configure File Storage Location
Once the dependencies are resolved, open src/main/resources/application.properties
, and add the following property to it
# The files uploaded through the API will be stored in this directory
file.upload-dir=./uploads
I gave uploads directory as my file storage location which would be under our project root path. This would directory will be created when we start our app (of course we will configure it). You can give your own path to be uploaded.
Binding Properties
Property values can be injected directly into your beans by using the @Value
annoation, accessed through Spring's Environment abstraction, or be bound to structured objects through @ConfigurationProperties
.
Create a package called property and inside the package create a class named FileStorageProperties.java
to bind the file property.
package com.fileapi.property;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Getter
@Setter
@ConfigurationProperties(prefix = "file")
public class FileStorageProperties {
private String uploadDir;
}
We have used @ConfigurationProperties(prefix = "file")
annotation so that it binds all the properties with prefix file
to the fields in our class on application startup. If you want to create an additional file property in properties file, all you need to do is to just add a field in our class.
Enabling Configuration Properties
To make @ConfigurationProperties
feature work, you need to add @EnableConfigurationProperties
to any configuration class. We will add it in our main class. So open src/main/java/com/fileapi/SpringFileApiApplication.java
and add the @EnableConfigurationProperties
annoation to it like this:
package com.fileapi;
import com.fileapi.property.FileStorageProperties;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
@SpringBootApplication
@EnableConfigurationProperties({
FileStorageProperties.class
})
public class SpringFileApiApplication {
public static void main(String[] args) {
SpringApplication.run(SpringFileApiApplication.class, args);
}
}
Services for File Upload and Download
Create a package service
under com.fileapi
and inside it create a class named FileService.java
with the following code:
package com.fileapi.service;
import com.fileapi.property.FileStorageProperties;
import lombok.extern.log4j.Log4j2;
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 java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.Objects;
@Log4j2
@Service
public class FileService {
private final Path fileStorageLocation;
@Autowired
public FileService(FileStorageProperties fileStorageProperties) {
// get the path of the upload directory
fileStorageLocation = Path.of(fileStorageProperties.getUploadDir());
try {
// creates directory/directories, if directory already exists, it will not throw exception
Files.createDirectories(fileStorageLocation);
} catch (IOException e) {
log.error("Could not create the directory where the uploaded files will be stored.", e);
}
}
public String storeFile(MultipartFile multipartFile) {
// get filename
String filename = StringUtils.cleanPath(Objects.requireNonNull(multipartFile.getOriginalFilename()));
try {
// check if the filename contains invalid characters
/*if (filename.contains("..")) {
throw new RuntimeException("Filename contains invalid path sequence " + filename);
}*/
// remove dots(.) in filename
filename = filename.substring(0, filename.lastIndexOf("."))
.replace(".", "") + "." + filename.substring(filename.lastIndexOf(".") + 1);
// convert path string to Path
Path targetLocation = fileStorageLocation.resolve(filename);
// copy file to the target location and replace existing file with the same name if exists
Files.copy(multipartFile.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);
return targetLocation.toString();
} catch (IOException e) {
throw new RuntimeException("Could not store file " + filename, e);
}
}
public Resource getFile(String filename) {
try {
Path file = fileStorageLocation.resolve(filename).normalize();
Resource resource = new UrlResource(file.toUri());
if (resource.exists() || resource.isReadable()) {
return resource;
} else {
throw new RuntimeException("Could not read file: " + filename);
}
} catch (MalformedURLException e) {
throw new RuntimeException("Could not retrieve file " + filename, e);
}
}
}
REST APIs for File Upload and Download
Create a package controller
under com.fileapi
and inside it create a class named FileController.java
with the following code:
package com.fileapi.controller;
import com.fileapi.service.FileService;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import static org.springframework.http.MediaType.parseMediaType;
@Log4j2
@RestController
@RequestMapping("/api/v1/file")
public class FileController {
private final FileService fileService;
@Autowired
public FileController(FileService fileService) {
this.fileService = fileService;
}
@PostMapping("/upload")
public ResponseEntity<?> uploadFile(@RequestParam("file") MultipartFile multipartFile) {
return ResponseEntity.ok(fileService.storeFile(multipartFile));
}
@GetMapping("/download/{filename:.+}")
public ResponseEntity<?> downloadFile(@PathVariable("filename") String filename, HttpServletRequest request) {
Resource fileResource = fileService.getFile(filename);
String contentType = null;
try {
contentType = request.getServletContext().getMimeType(fileResource.getFile().getAbsolutePath());
} catch (IOException e) {
log.error("Could not determine file type.");
}
if (contentType == null) {
contentType = "application/octet-stream";
}
return ResponseEntity.ok()
.contentType(parseMediaType(contentType))
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileResource.getFilename() + "\"")
.body(fileResource);
}
}
Testing the API via Postman
As we have created our API, let's run the application and test the APIs. Start the spring boot application and open Postman. Spring Boot runs on port 8080 by default, it can be accessed at http://localhost:8080.
Upload File
Download File
The souce code is available at github
Thanks for reading!