Javascript required
Skip to content Skip to sidebar Skip to footer

Multipart File Upload Angular and Spring Boot

1- Objective of lesson

In this lesson, I am going to guide you for creating a File Upload application usingSpring Boot andAngularJS.Below is the preview epitome of the application to be performed by united states of america:

Notify on the interface when uploading fails:

Display the listing of uploaded files and handle downloading when an user clicks a link.

two- Create a Spring Boot Project

On theEclipse,create aLeap Boot​​​​​​​project:

pom.xml

                          <?xml version="i.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"     xmlns:xsi="http://world wide web.w3.org/2001/XMLSchema-instance"     xsi:schemaLocation="http://maven.apache.org/POM/iv.0.0     http://maven.apache.org/xsd/maven-4.0.0.xsd">          <modelVersion>4.0.0</modelVersion>      <groupId>org.o7planning</groupId>     <artifactId>SpringBootFileUploadAngularJS</artifactId>     <version>0.0.ane-SNAPSHOT</version>     <packaging>jar</packaging>      <proper name>SpringBootFileUploadAngularJS</name>     <description>Spring Kicking + File Upload + AngularJS</clarification>      <parent>         <groupId>org.springframework.boot</groupId>         <artifactId>spring-boot-starter-parent</artifactId>         <version>two.0.0.RELEASE</version>         <relativePath/> <!-- lookup parent from repository -->     </parent>      <properties>         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>         <projection.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>         <java.version>ane.8</coffee.version>     </backdrop>      <dependencies>         <dependency>             <groupId>org.springframework.boot</groupId>             <artifactId>jump-kicking-starter-thymeleaf</artifactId>         </dependency>         <dependency>             <groupId>org.springframework.boot</groupId>             <artifactId>spring-boot-starter-web</artifactId>         </dependency>          <dependency>             <groupId>org.springframework.kicking</groupId>             <artifactId>spring-kick-starter-test</artifactId>             <scope>examination</scope>         </dependency>     </dependencies>      <build>         <plugins>             <plugin>                 <groupId>org.springframework.kick</groupId>                 <artifactId>spring-boot-maven-plugin</artifactId>             </plugin>         </plugins>     </build>   </project>                      

SpringBootFileUploadAngularJsApplication.java

                          parcel org.o7planning.sbfileupload;  import org.springframework.kick.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;  @SpringBootApplication public class SpringBootFileUploadAngularJsApplication {      public static void main(Cord[] args) {         SpringApplication.run(SpringBootFileUploadAngularJsApplication.form, args);     }  }                      

iii- Grade, Controller, Exception Handler

TheUploadForm form represents for the data of HTMLform.

UploadForm.java

                          bundle org.o7planning.sbfileupload.course;  import org.springframework.web.multipart.MultipartFile;  public class UploadForm {      private String clarification;      individual MultipartFile[] files;      public Cord getDescription() {         render description;     }      public void setDescription(String description) {         this.description = description;     }      public MultipartFile[] getFiles() {         return files;     }      public void setFiles(MultipartFile[] files) {         this.files = files;     }  }                      

MainController.java

                          bundle org.o7planning.sbfileupload.controller;  import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping;  @Controller public class MainController {      @GetMapping("/")     public String index() {         render "upload";     }  }                      

The MainRESTController class definesRest APIs to process the information of the files uploaded by users. TheseRest APIs volition be called by theAngularJS (See in theUploadFileCtrl.js).

MainRESTController.coffee

                          parcel org.o7planning.sbfileupload.restcontroller;  import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.nio.file.Files; import coffee.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List;  import org.o7planning.sbfileupload.form.UploadForm; import org.springframework.core.io.Resource; import org.springframework.core.io.UrlResource; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.notation.GetMapping; import org.springframework.spider web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.spider web.bind.notation.RestController; import org.springframework.web.multipart.MultipartFile;  @RestController public class MainRESTController {      // Linux: /dwelling house/{user}/examination     // Windows: C:/Users/{user}/test     private static String UPLOAD_DIR = Organization.getProperty("user.dwelling") + "/examination";       @PostMapping("/residuum/uploadMultiFiles")     public ResponseEntity<?> uploadFileMulti(@ModelAttribute UploadForm form) throws Exception {          System.out.println("Description:" + class.getDescription());          String result = null;         try {              effect = this.saveUploadedFiles(form.getFiles());          }         // Hither Catch IOException merely.         // Other Exceptions catch past RestGlobalExceptionHandler class.         catch (IOException e) {             e.printStackTrace();             return new ResponseEntity<>("Mistake: " + e.getMessage(), HttpStatus.BAD_REQUEST);         }          render new ResponseEntity<String>("Uploaded to: " + issue, HttpStatus.OK);     }      // Save Files     private String saveUploadedFiles(MultipartFile[] files) throws IOException {          // Make sure directory exists!         File uploadDir = new File(UPLOAD_DIR);         uploadDir.mkdirs();          StringBuilder sb = new StringBuilder();          for (MultipartFile file : files) {              if (file.isEmpty()) {                 continue;             }             String uploadFilePath = UPLOAD_DIR + "/" + file.getOriginalFilename();              byte[] bytes = file.getBytes();             Path path = Paths.go(uploadFilePath);             Files.write(path, bytes);              sb.append(uploadFilePath).suspend(", ");         }         render sb.toString();     }      @GetMapping("/rest/getAllFiles")     public List<String> getListFiles() {         File uploadDir = new File(UPLOAD_DIR);          File[] files = uploadDir.listFiles();          List<String> listing = new ArrayList<Cord>();         for (File file : files) {             list.add together(file.getName());         }         return list;     }      // @filename: abc.zilch,..     @GetMapping("/rest/files/{filename:.+}")     public ResponseEntity<Resource> getFile(@PathVariable Cord filename) throws MalformedURLException {         File file = new File(UPLOAD_DIR + "/" + filename);         if (!file.exists()) {             throw new RuntimeException("File non found");         }         Resource resource = new UrlResource(file.toURI());         return ResponseEntity.ok()                 .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + file.getName() + "\"")                 .body(resources);     }  }                      

The default size of the file uploaded to the Server doesn't exceed1MB. And if an user uploads a lot of files at the same time, full size of the files doesn't also exceed1MB. Withal, you lot tin configure to change these parameters.

awarding.properties

                          leap.servlet.multipart.max-file-size=1MB spring.servlet.multipart.max-request-size=5MB  leap.thymeleaf.cache=false                      

RestGlobalExceptionHandler is a custom class, extended from the ResponseEntityExceptionHandler grade. In this course, you lot can handle exceptions thrown from Balance methods. This will help you handle the exceptions centralized at a location instead of treatment an exception at each REST method.

RestGlobalExceptionHandler.coffee

                          packet org.o7planning.sbfileupload.exceptionhandler;  import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.spider web.bind.notation.ControllerAdvice; import org.springframework.web.demark.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.spider web.multipart.MultipartException; import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;   import javax.servlet.http.HttpServletRequest;   @ControllerAdvice public class RestGlobalExceptionHandler extends ResponseEntityExceptionHandler {       // Catch max file size Exception.     @ExceptionHandler(MultipartException.class)     @ResponseBody     public ResponseEntity<?> handleControllerException(HttpServletRequest asking, Throwable ex) {           HttpStatus status = this.getStatus(request);         render new ResponseEntity<String>("(Bulletin in RestGlobalExceptionHandler *): " + ex.getMessage(), status);     }       // Catch Other Exception     @ExceptionHandler(Exception.class)     @ResponseBody     public ResponseEntity<?> handleControllerRootException(HttpServletRequest request, Throwable ex) {           HttpStatus condition = this.getStatus(asking);         return new ResponseEntity<Cord>("(Message in RestGlobalExceptionHandler **): " + ex.getMessage(), condition);     }       private HttpStatus getStatus(HttpServletRequest request) {         Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");         if (statusCode == naught) {             render HttpStatus.INTERNAL_SERVER_ERROR;         }         return HttpStatus.valueOf(statusCode);     }   }                      

4- Javascript & View (Thymeleaf)

upload.html

                          <!DOCTYPE html> <html xmlns:thursday="http://world wide web.thymeleaf.org">    <head>       <title>Spring Kick File Upload with AngularJS</championship>       <meta charset="utf-8" />       <!-- Cheque other AngularJS version at: -->       <!-- https://lawmaking.angularjs.org/1.6.9/docs/misc/downloading -->       <script          src="https://ajax.googleapis.com/ajax/libs/angularjs/one.6.9/angular.min.js"></script>       <script src="/js/MainApp.js"></script>       <script src="/js/UploadFileCtrl.js"></script>       <script src="/js/GetFilesCtrl.js"></script>    </head>    <trunk ng-app="MainApp">       <h2>Jump Boot File Upload with AngularJS</h2>       <div ng-controller="UploadFileController">          <form>             Description: <br/>             <input type="text" name="description" ng-model="myForm.description" fashion="width:350px;"/>             <br/><br/>                              File to upload (i): <input type="file" file-model="myForm.files[0]"/><br />                   File to upload (two): <input blazon="file" file-model="myForm.files[1]"/><br />                 File to upload (three): <input type="file" file-model="myForm.files[2]"/><br />                 File to upload (4): <input type="file" file-model="myForm.files[3]"/><br />                 File to upload (5): <input type="file" file-model="myForm.files[4]"/><br />                 <button blazon="push button" ng-click="doUploadFile()">Upload</push>          </grade>          <h2>Upload Results:</h2>          <div style="border:1px solid #ccc;padding: 5px;">             <span ng-demark="uploadResult"></span>          </div>       </div>       <!-- Get Files -->       <60 minutes>       <div ng-controller="GetFilesController">          <push type="push button" ng-click="getAllFiles()">Become All Files</push button>          <ul>             <li ng-repeat="file in allFiles">                <a href='/rest/files/{{file}}'>{{file}}</a>             </li>          </ul>       </div>    </trunk> </html>                      

In theAngularJS, use the ng-model attribute to assistance you lot with two-way bounden betwixtInput element ofForm andModel, which ways that if the data of theModel changes, the interface of Inputelement will be updated and vice versa, if an user changes the interface of (Input element), the Model will be updated.

Unfortunately, the ng-model aspect does non support the two-way bounden between Model and Input[file], therefore, y'all need to define an directive called "fileModel" to build the 2-way binding between the Model and the Input[file]. This directive is defined in the MainApp.js:

js/MainApp.js

                          // main app. var mainApp = athwart.module('MainApp', []);   // DIRECTIVE - FILE MODEL mainApp.directive('fileModel', ['$parse', function ($parse) {     render {        restrict: 'A',        link: function(scope, chemical element, attrs) {           var model = $parse(attrs.fileModel);           var modelSetter = model.assign;                      element.demark('change', function(){              telescopic.$apply(role(){                 modelSetter(scope, element[0].files[0]);              });           });        }     };      }]);                      

TheUploadFileCtrl.js file containsAngularJS functions to control uploading files to theServer.

js/UploadFileCtrl.js

                          // CONTROLLER UPLOAD FILE mainApp.controller('UploadFileController', function($scope, $http) {      $telescopic.uploadResult ="";          $scope.myForm = {         description: "",         files: []     }      $telescopic.doUploadFile = function() {            var url = "/rest/uploadMultiFiles";           var information = new FormData();          data.suspend("description", $telescopic.myForm.description);         for (i = 0; i < $scope.myForm.files.length; i++) {             data.append("files", $scope.myForm.files[i]);         }          var config = {             transformRequest: angular.identity,             transformResponse: angular.identity,             headers: {                 'Content-Blazon': undefined             }         }                  $http.post(url, data, config).then(             // Success             function(response) {                 $scope.uploadResult =  response.information;             },             // Error             office(response) {                 $scope.uploadResult = response.information;             });     };  });                      

The GetFilesCtrl.js file contains theAngularJS functions to control obtaining the list of files uploaded to theServer.

js/GetFilesCtrl.js

                          mainApp.controller('GetFilesController', part($telescopic, $http) {      $scope.allFiles = [];       $scope.getAllFiles = function() {            // Balance URL:         var url = "/rest/getAllFiles";         $http.get(url).then(             // Success             function(response) { alert("OK");                 $telescopic.allFiles = response.information;             },             // Error             function(response) {                 alert("Error: " + response.data);             }         );     }; });                      

watkinmarly1944.blogspot.com

Source: https://o7planning.org/11673/spring-boot-file-upload-with-angularjs