Thursday, May 17, 2018

File Uploading in Spring MVC using thymeleaf and spring boot


File uploading is one of the very basic requirement now a day where user required to upload a file on server.
There are so many ways to upload a file but in this tutorial we will talk about the file upload in spring mvc using thymeleaf.


So lets start.

Pseudo code: (Only CSV and Zip are allowed to upload)
In this tutorial we will first create on web page 
this page will have a form whose action will call a spring controller
under this spring controller we will have the file upload logic.
we also define the server directory where we want to upload the file.
After file successfully uploaded , we will show the message on webpage.

Implementation code: ( You can download the source code from Github )

First we will see the project Structure 


Lets first see the pom.xml to see all the dependency

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>

 <groupId>com.programinjava.learn</groupId>
 <artifactId>FileUploadExample</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>jar</packaging>

 <name>FileUploadExample</name>
 <description>Demo project for Spring Boot</description>

 <parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.0.2.RELEASE</version>
  <relativePath/> <!-- lookup parent from repository -->
 </parent>

 <properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  <java.version>1.8</java.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>
  <dependency>
   <groupId>org.webjars</groupId>
   <artifactId>jquery</artifactId>
   <version>3.3.1</version>
  </dependency>
  <dependency>
   <groupId>org.webjars</groupId>
   <artifactId>bootstrap</artifactId>
   <version>3.3.7</version>
  </dependency>
 </dependencies>

 <build>
  <plugins>
   <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
   </plugin>
  </plugins>
 </build>


</project>


Here we have used below dependencies

  1. Thymeleaf
  2. Bootstrap
  3. Spring web
After this we will see the Controller class

package com.programinjava.learn.controller;

import java.util.regex.Pattern;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
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 org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.programinjava.learn.service.StorageService;

@Controller
public class UploadController {
 
 @Autowired
 StorageService storageService;
 
// CHANGE IT ACCORDING TO YOUR LOCATION
 private final String UPLOAD_FILE_LOCATION="C:\\programinjava_workspace";
 
 @PostMapping("/upload")
 public String singleFileUpload(@RequestParam("file") MultipartFile file, RedirectAttributes redirectAttributes) {

  if (file.isEmpty()) {
   redirectAttributes.addFlashAttribute("message", "Please select a file to upload");
   return "redirect:uploadStatus";
  }
  String UploadedFolderLocation = UPLOAD_FILE_LOCATION+"/";
  String fileName = null;
//   this is done to work on IE as well
  String pattern = Pattern.quote(System.getProperty("file.separator"));
  String[] str = file.getOriginalFilename().split(pattern);
  if (str.length > 0)
   fileName = str[str.length - 1];
  else
   fileName = str[0];
  if(!storageService.store(file, fileName,UPLOAD_FILE_LOCATION))
  {
   redirectAttributes.addFlashAttribute("message", "Error occurred while uploading the file");
   redirectAttributes.addFlashAttribute("status", "false");
   return "redirect:/uploadStatus";
  }
  redirectAttributes.addFlashAttribute("message", "You successfully uploaded '" + fileName + "'");
  redirectAttributes.addFlashAttribute("status", "true");
  return "redirect:/uploadStatus";
 }
 
 @GetMapping("/uploadStatus")
 public String uploadStatus(ModelMap m) {
  return "Homepage";
 }
 
 @GetMapping("/upload")  
 public String displayHomePageForAlarm() {
  return "Homepage";
 }

}
// CHANGE IT ACCORDING TO YOUR LOCATION
 private final String UPLOAD_FILE_LOCATION="C:\\programinjava_workspace";
NOTE : Change the location according to your local settings.
Now we will see the Service class : In this class we have created method called store will will actually store the data from client side to server side
StoreService.java

package com.programinjava.learn.service;

import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;

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 StorageService {


 private  Path rootLocation = Paths.get("data/input_data");

 public boolean store(MultipartFile file,String fileName ,String fileLocation){
  try {
    rootLocation = Paths.get(fileLocation);

   if(Files.copy(file.getInputStream(), this.rootLocation.resolve(fileName),StandardCopyOption.REPLACE_EXISTING)>0)
    return true;
  } catch (Exception e) {
   throw new RuntimeException("FAIL!" +e.getMessage());
  }
  return false;
 }

 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("FAIL!");
  }
 }

 public void deleteAll(String path) {
  if(path!=null && !path.isEmpty())
  {
   FileSystemUtils.deleteRecursively(Paths.get(path).toFile());
   
  }
  else
   FileSystemUtils.deleteRecursively(rootLocation.toFile());
 }


}
Now let see the HTML template file

<!DOCTYPE html>
<html xmlns:th="http://thymeleaf.org">
<head>
<title>File Upload Example</title>
<link href="webjars/bootstrap/3.3.7/css/bootstrap.min.css"
 rel="stylesheet" />
<script type="text/javascript" src="webjars/jquery/3.3.1/jquery.min.js"></script>
<script src="webjars/bootstrap/3.3.7/js/bootstrap.min.js"></script>

</head>
<script th:inline="javascript">
 /*<![CDATA[*/
 var _validFileExtensions = [ ".csv", ".zip" ];
 function Validate(oForm) {
  var arrInputs = oForm.getElementsByTagName("input");
  for (var i = 0; i < arrInputs.length; i++) {
   var oInput = arrInputs[i];
   if (oInput.type == "file") {
    var sFileName = oInput.value;
    if (sFileName.length == 0) {

     alert("Please select a file to upload");
     return false;
    }
    if (sFileName.length > 0) {
     var blnValid = false;
     for (var j = 0; j < _validFileExtensions.length; j++) {
      var sCurExtension = _validFileExtensions[j];
      if (sFileName.substr(
        sFileName.length - sCurExtension.length,
        sCurExtension.length).toLowerCase() == sCurExtension
        .toLowerCase()) {
       blnValid = true;
       break;
      }
     }

     if (!blnValid) {
      alert("Invalid File Extension");
      return false;
     }
    }
   }
  }

  return true;
 }
  
 /*]]>*/
</script>

<body>

 <div class="container-fluid padding-0">
  <div class="row padding-0">
   
   <div class="col-md-4">
    <h2>File Upload Example</h2>
   </div>
   <div class="col-md-4" align="right"></div>
  </div>
 </div>
 <nav role="navigation" id="trainingset-container-id"
  class="navbar navbar-default">
  <div class="row" style="margin-top: 10px;">
   <div class="col-md-2">
    <B>Upload File</B>
   </div>
   <div class="col-md-6">
    <form method="POST" action="/upload"
     onsubmit="return Validate(this);" enctype="multipart/form-data">
     <div class="col-sm-6">

      <input type="file" name="file"  />
     </div>
     <div class="col-sm-6">
      <input type="submit" class="btn btn-success btn-sm" value="Upload data" />
     </div>
    </form>
   </div>
   
  </div>
 </nav>
  <div id="messageboxid">
   <div id="uploadstatus" th:if="${message}">
    <B>Status Of Uploaded File</B>
    <h6 th:text="${message}" />
   </div>
  </div>
  
</body>
</html>
Thats it ,

How to run the webpage

you need to hit the below URL
http://localhost:8080/upload

you will be able to see the homepage and then you just need to upload the file and you will get the successful message once uploaded.

Hope this will help you !!

Read Also
  1. Spring Boot and Hibernate Tutorials - Application using Spring Boot
  2. What is Spring boot ?
  3. How to read value from property file in spring boot ?
  4. First Rest API Application - Top Spring Framework Interview Questions
Thanks for reading

0 comments:

Post a Comment