Upload files in Spring Boot application using Commons FileUpload
MultipartFile
interface. In this post, we will see how we can use the Commons FileUpload library and the wrapper implementation CommonsMultipartFile
provided by the Spring framework.Update the pom.xml
We will update the maven dependencies to include commons-io
and commons-fileupload
. We will use the FilenameUtils
class in commons-io
to normalize the file name of the uploaded file.
<dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.8.0</version> </dependency> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.4</version> </dependency>
Configuring CommonsMultipartResolver
The HTML is going to be the same as shown in the post here. For the Spring framework to make use of Commons FileUpload we need to configure CommonsMultipartResolver
and expose it as a @Bean
as shown below:
@Value("${spring.servlet.multipart.max-file-size}") String maxFileSize; @Value("${spring.servlet.multipart.max-request-size}") String maxRequestSize; @Bean public CommonsMultipartResolver commonsMultipartResolver(){ CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver(); commonsMultipartResolver.setMaxUploadSize(DataSize.parse(maxRequestSize).toBytes()); commonsMultipartResolver.setMaxUploadSizePerFile(DataSize.parse(maxFileSize).toBytes()); return commonsMultipartResolver; }
We would be making use of the Spring Boot’s max file size and max request size attributes to configure the CommonsMultipartResolver
.
Implement file copy using CommonsMultipart
In our FileService
class we will provide a new method copyFileUsingCommons
as shown below:
@Value("${app.document-root}")String documentRoot; public void copyFileUsingCommons(List<CommonsMultipartFile> uploadedFiles) throws IOException{ try { Path docRootPath = Path.of(documentRoot); if ( !Files.exists(docRootPath)){ Files.createDirectory(docRootPath); } for (CommonsMultipartFile multipartFile : uploadedFiles) { log.debug("Multipart storage location {}", multipartFile.getStorageDescription()); copy(multipartFile); } } catch (IOException e) { log.error("Error occurred while copying file", e); throw e; } } private void copy(MultipartFile multipartFile) throws IOException{ String fileName = multipartFile.getOriginalFilename(); String normalizedFileName = FilenameUtils.normalize(fileName); multipartFile.transferTo(Path.of(documentRoot, normalizedFileName)); }
By default commons file upload keeps the file whose size <= 10KB in memory and those > 10KB are moved to a temporary directory on the server before they are copied to the required destination. This limit can be changed while configuring the CommonsMultipartResolver
.
By default the Spring’s implementation of MultipartFile
writes all files to temporary directory. And this can be controlled by changing the value of the property: spring.servlet.multipart.file-size-threshold
in your application.properties
file
Update the file upload API
Finally we will update the file upload API to accept parameter of type List<CommonsMultipartFile>
and to use the new method copyFileUsingCommons
:
@PostMapping("/upload") public ResponseEntity<?> handleFileUpload( @RequestParam("uploaded-file") List<CommonsMultipartFile> uploadedFiles) throws IOException { log.debug("Uploaded files size : {}", uploadedFiles.size()); fileService.copyFileUsingCommons(uploadedFiles); return ResponseEntity.ok().build(); }
The StandardMultipartFile
implementation uses javax.servlet.http.Part
to represent the parts of the file uploaded by the user whereas CommonsMultipartFile
implementation uses org.apache.commons.fileupload.FileItem
to represent the parts of file uploaded by the user.
The complete code can be found in the GitHub project here.