Uploading and downloading files are very common tasks for which developers need to write code in their applications.
In this article, You’ll learn how to upload and download files in a RESTful spring boot web service.
We’ll first build the REST APIs for uploading and downloading files, and then test those APIs using Postman. We’ll also write front-end code in javascript to upload files.
Following is the final version of our application -
All right! Let’s get started.
Creating the Application
Let’s generate our application using . Fire up your terminal, and type the following command to generate the app -
$ spring init --name=file-demo --dependencies=web file-demoUsing service at https://start.spring.ioProject extracted to '/Users/rajeevkumarsingh/spring-boot/file-demo'
You may also generate the application through web tool by following the instructions below -
- Open
- Enter file-demo in the “Artifact” field.
- Add Web in the dependencies section.
- Click Generate Project to download the application.
That’s it! You may now unzip the downloaded application archive and import it into your favorite IDE.
Configuring Server and File Storage Properties
First thing First! 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 src/main/resources/application.properties
file, and add the following properties to it -
## MULTIPART (MultipartProperties)# Enable multipart uploadsspring.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 # All files uploaded through the REST API will be stored in this directory file.upload-dir=./uploads
You may change the above properties depending on your project requirements.
Automatically binding properties to a POJO class
Spring Boot has an awesome feature called 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 com.example.filedemo.property
package to bind all the file storage properties -
package com.example.filedemo.property; import org.springframework.boot.context.properties.ConfigurationProperties; @ConfigurationProperties(prefix = "file") public class FileStorageProperties { private String uploadDir; public String getUploadDir() { return uploadDir; } public void setUploadDir(String uploadDir) { this.uploadDir = uploadDir; } }
The @ConfigurationProperties(prefix = "file")
annotation does its job on application startup and binds all the properties with prefix file
to the corresponding fields of the POJO class.
If you define additional file
properties in future, you may simply add a corresponding field in the above class, and spring boot will automatically bind the field with the property value.
Enable Configuration Properties
Now, To enable the ConfigurationProperties
feature, you need to add annotation to any configuration class.
Open the main class src/main/java/com/example/filedemo/FileDemoApplication.java
, and add the @EnableConfigurationProperties
annotation to it like so -
package com.example.filedemo; import com.example.filedemo.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 FileDemoApplication { public static void main(String[] args) { SpringApplication.run(FileDemoApplication.class, args); } }
Writing APIs for File Upload and Download
Let’s now write the REST APIs for uploading and downloading files. Create a new controller class called FileController
inside com.example.filedemo.controller
package.
Here is the complete code for FileController
-
package com.example.filedemo.controller; import com.example.filedemo.payload.UploadFileResponse; import com.example.filedemo.service.FileStorageService; 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.*; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.support.ServletUriComponentsBuilder; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; @RestController public class FileController { private static final Logger logger = LoggerFactory.getLogger(FileController.class); @Autowired private FileStorageService fileStorageService; @PostMapping("/uploadFile") public UploadFileResponse uploadFile(@RequestParam("file") MultipartFile file) { String fileName = fileStorageService.storeFile(file); String fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath() .path("/downloadFile/") .path(fileName) .toUriString(); return new UploadFileResponse(fileName, fileDownloadUri, file.getContentType(), file.getSize()); } @PostMapping("/uploadMultipleFiles") public ListuploadMultipleFiles(@RequestParam("files") MultipartFile[] files) { return Arrays.asList(files) .stream() .map(file -> uploadFile(file)) .collect(Collectors.toList()); } @GetMapping("/downloadFile/{fileName:.+}") public ResponseEntity 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(