The following two tabs change content below.
Hi, I have written and developed this site to share my experience and ideas with other colleagues. I also started to prepare interview questions and answers for job seekers. I hope it will help you a lot.

In this post I am going to explain file uploading using Spring Boot and Angularjs. I am going to build a project for this functionality and will discuss on the technology with a simple example.

Below is the project structure which by default we need to follow for spring boot. Full project code you can download from my GIT account

 

fileupload_project_structureProject has been created with name “FileUpload” and in this we are going to use Spring boot for business logic. So creating controller/api, service and main application components.

For front end layer using angularjs and for responsive UI using bootstrap. I have downloaded all required library and kept on local under project directory like /js/lib and /css/lib.

For project building using Maven build tool.

Before to start development make sure you have following dependency in your pom.xml file.

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-thymeleaf</artifactId>
 <version>1.5.8.RELEASE</version>
 </dependency>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
 <version>1.5.8.RELEASE</version>
 </dependency>
<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-tomcat</artifactId>
 <version>1.5.9.RELEASE</version>
 </dependency>

So now one by one I am going to explain use of these dependencies:

1. spring-boot-starter-thymeleaf :

Thymeleaf is a Java library. It is an XML/XHTML/HTML5 template engine able to apply a set of transformations to template files in order to display data and/or text produced by your applications.
The main goal of Thymeleaf is to provide an elegant and well-formed way of creating templates. In order to achieve this, it is based on XML tags and attributes that define the execution of predefined logic on the DOM (Document Object Model), instead of explicitly writing that logic as code inside the template.

Its architecture allows a fast processing of templates, relying on intelligent caching of parsed files in order to use the least possible amount of I/O operations during execution.

2. spring-boot-starter-web : 

Starter for building web, including RESTful, applications using Spring MVC. Its providing the feature to develop spring application with 0% configuration.

3. spring-boot-starter-tomcat : 

Starter for using Tomcat as the embedded servlet container. Default servlet container starter used by spring-boot-starter-web. So now we no need external tomcat server for testing we can use this embedded server.

Note: In this project I am using packaging as .war file but you can change according to your requirement as .war or .jar based on your requirement. below is the tag

<packaging>war</packaging>

Below is the completed pom.xml file:

<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/maven-v4_0_0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>com.kpblogs</groupId>
 <artifactId>FileUpload</artifactId>
 <packaging>war</packaging>
 <version>0.0.1-SNAPSHOT</version>
 <name>FileUpload Maven Webapp</name>
 <url>http://maven.apache.org</url>
 <dependencies>
 <dependency>
 <groupId>junit</groupId>
 <artifactId>junit</artifactId>
 <version>3.8.1</version>
 <scope>test</scope>
 </dependency>


 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-thymeleaf</artifactId>
 <version>1.5.8.RELEASE</version>
 </dependency>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
 <version>1.5.8.RELEASE</version>
 </dependency>

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-tomcat</artifactId>
 <version>1.5.9.RELEASE</version>
 </dependency>


 </dependencies>
 <build>
 <finalName>FileUpload</finalName>
 </build>
</project>

So now we are good with dependency now lets write the API for file upload. For API we need to  write a RestController who will receive the MultiPartFile request parameter as below  FileUploadController.java:

package com.kpblogs.fileupload.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.kpblogs.fileupload.service.FileUploadService;

@RestController
@RequestMapping("/api")
public class FileUploadController {

@Autowired
 FileUploadService fileUploadService;
 
 @PostMapping("/fileUpload")
 public String fileUpload(@RequestParam("uploadfile") MultipartFile file) throws Exception {
 try {
 fileUploadService.store(file);
 return "File " + file.getName()+" uploaded successfully!!";
 } catch (Exception e) {
 throw new Exception(e.getMessage());
 }
 }
 
}

now explaining all annotation one by one:

@RestController

Earlier before 4.0 spring was using common annotation (@Controller) for both Rest API and also for view resolver but to make it simple spring given @RestController. @RestController is a stereotype annotation that combines @ResponseBody and @Controller. More than that, it gives more meaning to your Controller and also may carry additional semantics in future releases of the framework.

@RequestMapping

To configure the mapping of web requests, you use the @RequestMapping annotation. The @RequestMapping annotation can be applied to class-level and/or method-level in a controller.

The class-level annotation maps a specific request path or pattern onto a controller. You can then apply additional method-level annotations to make mappings more specific to handler methods.

Here is an example of the @RequestMapping annotation applied to both class and methods.

@RequestMapping("/api") //Class level mapping 
public class FileUploadController {

@Autowired
 FileUploadService fileUploadService;
 
 @PostMapping("/fileUpload") //Method level mapping Post mapping means POST method will be used to access this URI 
 public String fileUpload(@RequestParam("uploadfile") MultipartFile file) throws Exception {

 

@Autowired

@Autowired annotation – We can use Spring @Autowired annotation for spring bean autowiring. @Autowired annotation can be applied on variables and methods for autowiring byType. We can also use @Autowired annotation on constructor for constructor based spring autowiring.

In the above class we are using @Autowired to inject the FileUploadService object into the method to complete file upload given below:

@Autowired
 FileUploadService fileUploadService;
 
 @PostMapping("/fileUpload")
 public String fileUpload(@RequestParam("uploadfile") MultipartFile file) throws Exception {
 try {
 fileUploadService.store(file);
 return "File " + file.getName()+" uploaded successfully!!";
 } catch (Exception e) {
 throw new Exception(e.getMessage());
 }
 }

So now we understand the controller part so lets move on service layer. To make this as service layer we are using @Service annotation. Below is full code of Service layer where we are taking MultiPartFile object and then coping to a destination location as given below FileUploadService.java:

package com.kpblogs.fileupload.service;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

@Service
public class FileUploadService {

@Value("${fileupload-destination}")
 private String fileDestination;
 
 public void store(MultipartFile file){
 try {
 Path rootLocation = Paths.get(fileDestination);
 Files.copy(file.getInputStream(), rootLocation.resolve(file.getOriginalFilename()));
 } catch (Exception e) {
 throw new RuntimeException(e.getMessage());
 }
 }
 
 
}

@Service – annotate classes at service layer level.

@Value – Used to inject the property file value to attribute. Means we are getting the file destination location from application.properties file.

Using java.nio to copy the file on destination location.

So now we are done with REST API and its time to create front end from where we will pass file object to this API.

lets start with Angularjs now. Like spring framework Angularjs also working on MVC design pattern. So we are going to create Application as given below fileUploadApp.js :

var fileUploadApp = angular.module('fileUploadApp', []);

fileUploadApp.directive('fileModel', ['$parse', function ($parse) {
 return {
 restrict: 'A',
 link: function(scope, element, attrs) {
 var model = $parse(attrs.fileModel);
 var modelSetter = model.assign;
 
 element.bind('change', function(){
 scope.$apply(function(){
 modelSetter(scope, element[0].files[0]);
 });
 });
 }
 };
}]);

and below we have controller. from where we will call Spring REST API. fileUploadController.js :

// CONTROLLER UPLOAD FILE
fileUploadApp.controller('fileUploadController', ['$scope', '$http', function($scope, $http){
 $scope.doUploadFile = function(){
 var file = $scope.uploadedFile;
 var url = "/FileUpload/api/fileUpload";
 
 var data = new FormData();
 data.append('uploadfile', file);
 
 var config = {
 transformRequest: angular.identity,
 transformResponse: angular.identity,
 headers : {
 'Content-Type': undefined
 }
 }
 
 $http.post(url, data, config).then(function (response) {
 $scope.uploadResult=response.data;
 }, function (response) {
 $scope.uploadResult=response.data;
 });
 };
}]);

In the above controller we are doing the async call  using $http.post and passing the FormData object with ‘uploadfile’ file property.

Inside the controller we have one function “doUploadFile” which will be called once from frontend user will click on “Upload” button. inside this function we have http call also and once we got response we are returning to front end using below line:

$scope.uploadResult=response.data;

we done with business and model layer now lets prepare view part using. Below is the code of template (view) fileUploadForm.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" >
<head>
 <title>Spring Boot - ANGULARJS UPLOAD FILES Example</title>
 <meta charset="utf-8" />
 <meta name="viewport" content="width=device-width, initial-scale=1" />
 <link rel="stylesheet" href="/FileUpload/css/lib/bootstrap.min.css"></link>
 <script src="/FileUpload/js/lib/angular.min.js"></script>
</head>

<body class="container" ng-app="fileUploadApp">

<div ng-controller="fileUploadController">
 <form class="form-horizontal">
 <div class="form-group">
 <label class="control-label col-sm-2" for="uploadfile">Upload File:</label>
 <div class="col-sm-5">
 <input class="form-control" type="file" file-model = "uploadedFile" placeholder="Upload File"></input>
 </div>
 </div>
 <div class="form-group"> 
 <div class="col-sm-offset-2 col-sm-10">
 <button type="submit" class="btn btn-default" ng-click = "doUploadFile()">Upload</button>
 </div>
 </div>
 </form>
 <hr/>
 <div class="col-sm-offset-2">
 <p ng-bind="uploadResult"></p>
 </div>
 </div>
 
 
 <script src="/FileUpload/js/fileUploadApp.js"></script>
 <script src="/FileUpload/js/fileUploadController.js"></script>
 
 <!-- jQuery library -->
 <script src="/FileUpload/js/lib/jquery.min.js"></script>
 <script src="/FileUpload/js/lib/bootstrap.min.js"></script>

</body>
</html>

In this template file we included all required library and Angularjs application and controller like below:

<body class="container" ng-app="fileUploadApp">

Note: controller will not work without application (ng-app)

<div ng-controller="fileUploadController">

For responsive layout I have used bootstrap. If you don’t want to use class=”container”, col-sm-2 etc please ignore these tags.

for file input given like:

 <input class="form-control" type="file" file-model = "uploadedFile" placeholder="Upload File"></input>

and called doUploadFile() method on the button click event like :

 <button type="submit" class="btn btn-default" ng-click = "doUploadFile()">Upload</button>

once we click upload button we will get success or failure message using like:

<p ng-bind="uploadResult"></p>

So now I am writing a controller who will load/initialize this template page as given below FileUploadPageController.java 

package com.kpblogs.fileupload.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class FileUploadPageController {
 
 @GetMapping("/fileUploadPage")
 public String fileUploadPage() {
 
 return "fileUploadForm";
 
 }
}

As discussed earlier @Controller we are using for ViewResolver body type content. So now in return type we are giving template file name without extension return “fileUploadForm” once we will call /fileUploadPage internally controller will load our template file fileUploadForm.html with the help of ViewResolver.

We all done with coding part now lets discuss on application.properties file. Spring boot with thymeleaf by default using /(root) as application context so if you want to change application content please put below property in  application.properties.

server.contextPath = /FileUpload

below we have application.properties:

fileupload-destination = C:\\Users\\kpal\\kpblogs\\
server.contextPath = /FileUpload

if you want to restrict file size during upload please use below property in the same file.

spring.http.multipart.max-file-size: limit total file size for each request.
spring.http.multipart.max-request-size: limit total request size for a multipart/form-data.

As we know spring boot giving the flexibility to test application with any other server or no need to deploy on server as given below :

 

package com.kpblogs.fileupload;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MainUploadApplication {

public static void main(String[] args) {

SpringApplication.run(MainUploadApplication.class, args);
 }

}

 

@SpringBootApplication I already explained in my earlier post how-to-build-rest-web-servicesapi-using-spring-framework

below is the running application screenshots for success:

fileupload_success

 

Full project code you can download from my GIT account

 

 

193 total views, 4 views today

Leave a Reply

Your email address will not be published. Required fields are marked *