Simplest and Easy way to Upload and Download Files in Java with Spring Boot
Uploading and Downloading Files is one of the core functionality that any Enterprise Application wants to incorporate. In this article, we will see How to Upload and Download Files in Java with Spring Boot.
Softwares used
- Spring Boot 2.0.3.RELEASE
- Thymeleaf
- Java 8
- Maven
- Eclipse
Maven Dependencies
Below are the key dependencies that we are using.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <maven-jar-plugin.version>2.6</maven-jar-plugin.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <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> <!--WebJars --> <dependency> <groupId>org.webjars</groupId> <artifactId>bootstrap</artifactId> <version>3.3.6</version> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>jquery</artifactId> <version>2.1.4</version> </dependency> <!--/WebJars --> </dependencies> |
Our code is built on top of Web Starter Application. We are using WebJars for Bootstrap and Jquery.
At the core of this application will be our service class – FileSystemStorageService.java. We will look at each of its functions in the rest of the article.
Initialization
1 2 3 4 5 6 7 8 9 |
@PostConstruct public void init() { this.uploadLocation = Paths.get(Constants.UPLOAD_LOCATION); try { Files.createDirectories(uploadLocation); } catch (IOException e) { throw new RuntimeException("Could not initialize storage", e); } } |
This code is executed after the service class object is created. In this init method, we try to create the directory where we want to upload our files.
Storing the file
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public void store(MultipartFile file) { String filename = StringUtils.cleanPath(file.getOriginalFilename()); try { if (file.isEmpty()) { throw new RuntimeException("Failed to store empty file " + filename); } // This is a security check if (filename.contains("..")) { throw new RuntimeException("Cannot store file with relative path outside current directory " + filename); } try (InputStream inputStream = file.getInputStream()) { Files.copy(inputStream, this.uploadLocation.resolve(filename), StandardCopyOption.REPLACE_EXISTING); } } catch (IOException e) { throw new RuntimeException("Failed to store file " + filename, e); } } |
This method will get a MultipartFile from Spring controller. The file name is then resolved relative to our upload directory and copied there.
File as Resource
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public Resource loadAsResource(String filename) { try { Path file = uploadLocation.resolve(filename); 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 read file: " + filename, e); } } |
Above code, converts a file that we want to download into a Resource. This resource is later pushed to download via the controller.
Now let us look at few controller methods which utilize above service class to achieve the functionality.
Handle File Upload
1 2 3 4 5 6 |
@RequestMapping(value = "/files/upload", method = RequestMethod.POST) public String handleFileUpload(@RequestParam("file") MultipartFile file, RedirectAttributes redirectAttributes) { storageService.store(file); redirectAttributes.addFlashAttribute("message", "You successfully uploaded " + file.getOriginalFilename() + "!"); return "redirect:/"; } |
Above method will kick off, when you upload a file from UI. The Spring controller receives a MultipartFile, which is then sent to storage service class.
Downloading a File
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
@RequestMapping(value = "/files/list", method = RequestMethod.GET) public String listFiles(Model model) { List<Path> lodf = new ArrayList<>(); List<HRefModel> uris = new ArrayList<>(); try { lodf = storageService.listSourceFiles(storageService.getUploadLocation()); for(Path pt : lodf) { HRefModel href = new HRefModel(); href.setHref(MvcUriComponentsBuilder .fromMethodName(UploadController.class, "serveFile", pt.getFileName().toString()) .build() .toString()); href.setHrefText(pt.getFileName().toString()); uris.add(href); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } model.addAttribute("listOfEntries", uris); return "file_list :: urlFileList"; } @GetMapping("/files/{filename:.+}") @ResponseBody public ResponseEntity<Resource> serveFile(@PathVariable String filename) { Resource file = storageService.loadAsResource(filename); return ResponseEntity.ok() .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + file.getFilename() + "\"") .body(file); } |
Downloading a file is 2 step process. First, we have to list all the files in the URL form and when the user clicks on any of the links, we will send the actual file.
Listing of files uses MvcUriComponentsBuilder to prepare the URL based on the method which is going to actually serve the file for download. When a user clicks on a file name headers and attachments is sent to the client.
Demo: Upload and Download Files in Java
Notice that we are allowing only text files to be uploaded. The upload button is enabled only when a user selects text file. The code for this is available in upload.js.
Once you select a text file and click on Upload, you will see the message that file is uploaded successfully.
You can check the files which we uploaded and listed on our page are physically available on our servers.
Conclusion
In this article, we have seen how Spring Boot has made Upload and Download Files in Java easy to implement.
The complete code is available at our GitHub repo. Please feel free to download and try.
Download Code
Hi can I get code for uploading files per user folder not in one folder
Hi , Could you please tell me like how to download the file the specific location in my local drive . Every time the file is downloaded in the “Downloads” folder by default. Can this behavior be changed ?
hi
i installed a program eclipse mars after java IDE on my computer
can you help me how to run this application, is it need install other programs?
hi
i install eclips mars after java IDE on my computer
can you help me how to run your application, it is need install other programs?
Yes I can help You
Hi, Thanks for the tutorial! I am working on a requirement that should allow the user select a source folder and then upload only the jpeg files in that folder to a server location. Please provide some input on how a folder selection can be implemented instead of a file.
Hey, thanks for the Tutorial. but i need a route specific in my local machine as ‘mypath/mypath/myfile.kmz’
Thank you
Hi Juan, Please check upload.js. See if you can add the your file extension in the allowed list and that should appear.
Hey, thanks for the Tutorial. It worked!
How do i change it, that i can upload any file (not just .txt files)?
I’ve already tried to change something in “upload.html” and “FileSystemStorageServie.java”, nut it didn’t work.
Thank you
Hi Andi,
Glad you found it useful.
To allow more extensions you need to change upload.js as well like
if (ext == 'txt' || ext == 'pdf') {
upload.html – you need to change the accept attribute of file input as
accept=".txt,.pdf"
FileSystemStorageService.java – you need to change creation of directory stream as
Files.newDirectoryStream(dir, "*.{txt,pdf}")
Let me know if this works for you.
not exist code in the link
Thanks, Lucario. The link is now updated.