In the past post, we had learned how to upload MultipartFile with SpringBoot and JQuery Ajax. Today, JavaSampleApproach shows how to create a Spring AngularJs MultipartFile application to download/upload file with SpringBoot, AngularJs and Bootstrap.
Related posts:
– MultipartFile – How to create Spring Ajax MultipartFile application to download/upload files | SpringBoot + JQuery Ajax + Bootstrap
– How to integrate Http Angularjs with Spring MVC | Spring Boot
– How to integrate Angular 4 with SpringBoot Web App and SpringToolSuite
– Angular 4 – Upload/Get MultipartFile to/from Spring Boot Server
I. Technologies
– Java 8
– Maven 3.6.1
– Spring Tool Suite: Version 3.8.4.RELEASE
– Spring Boot: 1.5.4.RELEASE
– JQuery
– Bootstrap
II. Practices
Create a SpringBoot project with below structure:
Step to do:
– Create SpringBoot project
– Create Storage Service
– Implement upload controller
– Implement AngularJs App
– Create upload page
– Init Storage for File System
– Run and check results
1. Create SpringBoot project
Open Spring Tool Suite, on main menu, choose File->New->Spring Starter Project, add project info, then press Next for needed dependencies:
– For Template Engines, choose Thymeleaf.
– For Web MVC, choose Web->Web.
Press Finish, Spring Boot project will be created successfully.
Open pom.xml file to check 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> |
2. Create Storage Service
Create StorageService with 4 functions:
– public void store(MultipartFile file)
: save a file
– public Resource loadFile(String filename)
: load a file
– public void deleteAll()
: remove all uploaded files
– public void init()
: create upload directory
package com.javasampleapproach.uploadfile.storage; import java.io.IOException; import java.net.MalformedURLException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; 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 StorageService { Logger log = LoggerFactory.getLogger(this.getClass().getName()); private final Path rootLocation = Paths.get("upload-dir"); public void store(MultipartFile file){ try { Files.copy(file.getInputStream(), this.rootLocation.resolve(file.getOriginalFilename())); } catch (Exception e) { throw new RuntimeException("FAIL!"); } } 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() { FileSystemUtils.deleteRecursively(rootLocation.toFile()); } public void init() { try { Files.createDirectory(rootLocation); } catch (IOException e) { throw new RuntimeException("Could not initialize storage!"); } } } |
3. Implement upload controller
Create a RestUploadController with 3 RequestMapping:
– @PostMapping("/api/uploadfile")
is used to upload files.
– @GetMapping("/api/getallfiles")
is used to get all uploaded files
– @GetMapping("/api/files/{filename:.+}")
is used to download files.
package com.javasampleapproach.uploadfile.controller; import java.util.ArrayList; 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.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; 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 org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder; import com.javasampleapproach.uploadfile.storage.StorageService; @RestController @RequestMapping("/api") public class RestUploadController { @Autowired StorageService storageService; List<String> files = new ArrayList<String>(); // Multiple file upload @PostMapping("/uploadfile") public String uploadFileMulti(@RequestParam("uploadfile") MultipartFile file) throws Exception { try { storageService.store(file); files.add(file.getOriginalFilename()); return "You successfully uploaded - " + file.getOriginalFilename(); } catch (Exception e) { throw new Exception("FAIL! Maybe You had uploaded the file before or the file's size > 500KB"); } } @GetMapping("/getallfiles") public List<String> getListFiles() {List<String> lstFiles = new ArrayList<String>(); try{ lstFiles = files.stream() .map(fileName -> MvcUriComponentsBuilder .fromMethodName(RestUploadController.class, "getFile", fileName).build().toString()) .collect(Collectors.toList()); }catch(Exception e){ throw e; } return lstFiles; } @GetMapping("/files/{filename:.+}") public ResponseEntity<Resource> getFile(@PathVariable String filename) { Resource file = storageService.loadFile(filename); return ResponseEntity.ok() .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + file.getFilename() + "\"") .body(file); } } |
Open application.properties file, configure multipart.max-file
:
spring.http.multipart.max-file-size=500KB spring.http.multipart.max-request-size=500KB |
– 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.
4. Implement AngularJs App
4.1 Create AngularJs application
Define AngularJs application in jsaApp.js file:
var jsaApp = angular.module('jsaUploadFileApp', []); // DIRECTIVE - FILE MODEL jsaApp.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]); }); }); } }; }]); |
Note: Angular’s ng-model
can NOT bind with file
input, so we need to create a custom directive fileModel
for binding data.
4.2 Implement upload controller
Create uploadFileCtrl.js file to implement uploadFileController controller:
// CONTROLLER UPLOAD FILE jsaApp.controller('uploadFileController', ['$scope', '$http', function($scope, $http){ $scope.doUploadFile = function(){ var file = $scope.uploadedFile; var url = "/api/uploadfile"; 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; }); }; }]); |
Note: with setting 'Content-Type': undefined
, the browser will automatically change the Content-Type to multipart/form-data
.
4.3 Implement get controller
Create a getFilesCtrl.js file to get all uploaded files:
jsaApp.controller('getFilesController', ['$scope', '$http', function($scope, $http){ $scope.doGetFiles = function(){ var url = "/api/getallfiles"; $http.get(url).then(function (response) { $scope.lstFiles = response.data; }, function (response) { alert(response.data); }); }; }]); |
5. Create upload page
– Create a Controller for uploading page:
package com.javasampleapproach.uploadfile.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; @Controller public class IndexController { @GetMapping("/") public String index() { return "upload"; } } |
– Use Bootstrap to implement upload page:
<!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" /> <!-- Latest compiled and minified CSS --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"></link> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script> </head> <body class="container" ng-app="jsaUploadFileApp"> <div ng-controller="uploadFileController"> <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> <div ng-controller="getFilesController"> <div class="col-sm-offset-2"> <button type="button" class="btn btn-primary btn-block" ng-click="doGetFiles()">Get Files</button> </div> <hr/> <div class="col-sm-offset-2" ng-model="lstFiles"> <ul> <li ng-repeat="file in lstFiles"><a href='{{file}}'>{{file}}</a></li> </ul> </div> </div> <script src="/js/jsaApp.js"></script> <script src="/js/uploadFileCtrl.js"></script> <script src="/js/getFilesCtrl.js"></script> <!-- jQuery library --> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> </body> </html> |
6. Init Storage for File System
In main class of the SpringBoot application, we use CommandLineRunner
interface for initialize StorageService:
package com.javasampleapproach.uploadfile; import javax.annotation.Resource; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import com.javasampleapproach.uploadfile.storage.StorageService; @SpringBootApplication public class SpringBootAngularJsMultipartFileApplication implements CommandLineRunner { @Resource StorageService storageService; public static void main(String[] args) throws Exception { SpringApplication.run(SpringBootAngularJsMultipartFileApplication.class, args); } @Override public void run(String... args) throws Exception { storageService.deleteAll(); storageService.init(); } } |
7. Run and check results
Build and Run the SpringBoot project with commandlines {mvn clean install
, mvn spring-boot:run
}
– Make a request http://localhost:8080/
:
-> See headers:
– Choose files and do Upload:
– List uploaded files:
– Click on a link to download the file:
III. Sourcecode
SpringBootAngularJSMultipartFile
can you do video on how to send file + Json object in single $http.post() request in Angularjs with spring boot