In the tutorial, we guide how to build a SpringBoot web-application to upload/download file with Thymeleaf engine and Bootstrap 4.
Contents
Technologies
- Java 8
- Maven 3.6.1
- Spring Tool Suite: Version 3.9.4.RELEASE
- Spring Boot: 2.0.2.RELEASE
- Bootstrap 4
Goal
We create a SpringBoot project as below:
-> Upload Form:
-> Download Form:
Practice
We create a SpringBoot project with below dependencies:
org.springframework.boot spring-boot-starter-thymeleaf org.springframework.boot spring-boot-starter-web
Frontend
Upload Multipart-Form
– Create /templates/multipartfile/uploadfile.html file:
Upload MultipartFile %MINIFYHTMLd3de0bf20f110ce4eca11061d904c6f916%%MINIFYHTMLd3de0bf20f110ce4eca11061d904c6f917%%MINIFYHTMLd3de0bf20f110ce4eca11061d904c6f918%%MINIFYHTMLd3de0bf20f110ce4eca11061d904c6f919%Upload MultipartFile to FileSystem
Retrieves Files
– Create /templates/multipartfile/listfiles.html file:
Upload MultipartFile %MINIFYHTMLd3de0bf20f110ce4eca11061d904c6f920%%MINIFYHTMLd3de0bf20f110ce4eca11061d904c6f921%%MINIFYHTMLd3de0bf20f110ce4eca11061d904c6f922%
Backend
File Storage Service
– Create interface FileStorage.java file:
package com.javasampleapproach.multipartfile.filestorage; import java.nio.file.Path; import java.util.stream.Stream; import org.springframework.core.io.Resource; import org.springframework.web.multipart.MultipartFile; public interface FileStorage { public void store(MultipartFile file); public Resource loadFile(String filename); public void deleteAll(); public void init(); public StreamloadFiles(); }
– Implement above interface by class FileStorageImpl.java:
package com.javasampleapproach.multipartfile.filestorage; 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.util.stream.Stream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.io.Resource; import org.springframework.core.io.UrlResource; import org.springframework.stereotype.Service; import org.springframework.util.FileSystemUtils; import org.springframework.web.multipart.MultipartFile; @Service public class FileStorageImpl implements FileStorage{ Logger log = LoggerFactory.getLogger(this.getClass().getName()); private final Path rootLocation = Paths.get("filestorage"); @Override public void store(MultipartFile file){ try { Files.copy(file.getInputStream(), this.rootLocation.resolve(file.getOriginalFilename())); } catch (Exception e) { throw new RuntimeException("FAIL! -> message = " + e.getMessage()); } } @Override public Resource loadFile(String filename) { try { Path file = rootLocation.resolve(filename); Resource resource = new UrlResource(file.toUri()); if(resource.exists() || resource.isReadable()) { return resource; }else{ throw new RuntimeException("FAIL!"); } } catch (MalformedURLException e) { throw new RuntimeException("Error! -> message = " + e.getMessage()); } } @Override public void deleteAll() { FileSystemUtils.deleteRecursively(rootLocation.toFile()); } @Override public void init() { try { Files.createDirectory(rootLocation); } catch (IOException e) { throw new RuntimeException("Could not initialize storage!"); } } @Override public StreamloadFiles() { try { return Files.walk(this.rootLocation, 1) .filter(path -> !path.equals(this.rootLocation)) .map(this.rootLocation::relativize); } catch (IOException e) { throw new RuntimeException("\"Failed to read stored file"); } } }
Upload/Download File Controller
– Firstly, create a simple data model FileInfo.java that contains information of a file:
package com.javasampleapproach.multipartfile.model; public class FileInfo { private String filename; private String url; public FileInfo(String filename, String url) { this.filename = filename; this.url = url; } public String getFilename() { return this.filename; } public void setFilename(String filename) { this.filename = filename; } public String getUrl() { return this.url; } public void setUrl(String url) { this.url = url; } }
– Implement controller UploadFileController.java:
package com.javasampleapproach.multipartfile.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; 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 com.javasampleapproach.multipartfile.filestorage.FileStorage; @Controller public class UploadFileController { @Autowired FileStorage fileStorage; @GetMapping("/") public String index() { return "multipartfile/uploadform.html"; } @PostMapping("/") public String uploadMultipartFile(@RequestParam("uploadfile") MultipartFile file, Model model) { try { fileStorage.store(file); model.addAttribute("message", "File uploaded successfully! -> filename = " + file.getOriginalFilename()); } catch (Exception e) { model.addAttribute("message", "Fail! -> uploaded filename: " + file.getOriginalFilename()); } return "multipartfile/uploadform.html"; } }
– Implement controller DownloadFileController.java:
package com.javasampleapproach.multipartfile.controller; import java.util.List; import java.util.stream.Collectors; 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.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder; import com.javasampleapproach.multipartfile.filestorage.FileStorage; import com.javasampleapproach.multipartfile.model.FileInfo; @Controller public class DownloadFileController { @Autowired FileStorage fileStorage; /* * Retrieve Files' Information */ @GetMapping("/files") public String getListFiles(Model model) { ListfileInfos = fileStorage.loadFiles().map( path -> { String filename = path.getFileName().toString(); String url = MvcUriComponentsBuilder.fromMethodName(DownloadFileController.class, "downloadFile", path.getFileName().toString()).build().toString(); return new FileInfo(filename, url); } ) .collect(Collectors.toList()); model.addAttribute("files", fileInfos); return "multipartfile/listfiles"; } /* * Download Files */ @GetMapping("/files/{filename}") public ResponseEntity downloadFile(@PathVariable String filename) { Resource file = fileStorage.loadFile(filename); return ResponseEntity.ok() .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + file.getFilename() + "\"") .body(file); } }
Note:
We can configure multipart.max-file
in application.properties to limit the size of uploaded file:
spring.http.multipart.max-file-size=500KB spring.http.multipart.max-request-size=500KB
Run & Check Results
Run the SpringBoot project, then makes upload/download requests ->
Upload File
-> Browser Network logs:
-> Stored files:
Retrieve Files
Download Files
-> Browser Network logs:
SourceCode
SpringUploadDownloadMultipartFile
Last updated on April 8, 2019.
the unit test?
Showing error in :fileName variable below used (error: fileName cant resolved to a variable)
public String getListFiles(Model model) {
model.addAttribute(“files”,
files.stream()
.map(fileName -> MvcUriComponentsBuilder
.fromMethodName(UploadController.class, “getFile”, fileName).build().toString())
.collect(Collectors.toList()));
model.addAttribute(“totalFiles”, “TotalFiles: ” + files.size());
return “listFiles”;
}
Hi Deepak Das,
Please detail about your case, If you have problems with starting, So the below video can help more:
https://youtu.be/VIn9xshqxKE
Regards,
If it is possible please try to provide an example with the using of streams and tests and restful without JSP and that stores to mysql or mongodb.
Thanks!
What about storing the MultipartFile in the Controller?
We use a requestMapping in
UploadController
to handle upload file:Then use
storageService
to storeMultipartFile
file.Document upload size is woring as excepcted in local. howver in jboss server it got failed with the error message
is there any configuration for below 2 property in jboss undertow config file
spring.http.multipart.max-file-size=500KB
spring.http.multipart.max-request-size=500KB
Hello Prathwish Hegde,
Spring Boot includes support for embedded Tomcat, Jetty, and Undertow servers.
So I think you should start with embedded Undertow as configuration in pom.xml file:
Regards,
JSA
thx!!!
i have a problem: the spring boot app runs perfect.. the files copied to “upload-dir”
but… when i change the app to .war and run in tomcat NOT FOUND x(
…. tryed to copy the entiry directory manually but still fails… x(
HELP pls!
Hi Adolf Mrls,
Do you have check the permission for create-read on your folder?
Can you try to work with absolute path of ‘upload-dir’.
Regards,
JSA
hi, i tried your code but when i want to test it with postman it replies with
{
“timestamp”: “2018-04-09T13:20:24.966+0000”,
“status”: 400,
“error”: “Bad Request”,
“message”: “Required request part ‘file’ is not present”,
“path”: “/”
}
please any help ?
Hi there,
Would you be open to discussing some observations I’ve made on grokonez.com? I think we can help to drive more traffic to yoursite, in addition to more sales.
If more sales/leads is what you’d like, just respond here, and I’ll have one of my consultants get in touch.
Thanks,
Liv
How can I save to the database? because in your example you are not saving. How could I do this???
Dear,
Here is the post for your question:
https://grokonez.com/spring-framework/spring-data/springboot-upload-download-multipartfile-to-mysql-bootstrap-4-jquery-ajax-spring-hibernate-jpa-lob
Regards,
Grokonez
what about saving in mongodb is it the same !!
Muchas gracias. ?Como puedo iniciar sesion?