In this post we will be discussing about using form data to upload file to a spring boot based REST server with angular js as client.We will have a sample project having a form to upload a file and once the file is uploaded, we will be displaying the same in a table with a download button and whenever this button is clicked the image will be downloaded in the browser. We will be using spring boot to ease our development. So let us get started with file upload with angular js and spring boot.
This article is based on AngularJs. You can visit my another article for latest version of Angular here - Angular Multiple File Upload
You can follow this article for Angular 8 integration with Spring Boot.
Project Structure
Following is the project structure which we will be creating.
Following is the final output of what we will be implementing here.
Maven Dependencies
spring-boot-starter-parent
: It provides useful Maven defaults. It also provides a dependency-management section so that you can omit version tags for existing dependencies.
spring-boot-starter-web
: It includes all the dependencies required to create a web app. This will avoid lining up different spring common project versions.
spring-boot-starter-tomcat
: It enable an embedded Apache Tomcat 7 instance, by default.This can be also marked as provided if you wish to deploy the war to any other standalone tomcat.
spring-boot-starter-data-jpa
: It provides key dependencies for Hibernate, Spring Data JPA and Spring ORM.
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.4.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> </dependency> </dependencies>
Controller Class Implementation
This class has rest endpoints exposed for file upload.It has also some endpoints exposed to download the document.
DocumentController.java@Controller @RequestMapping(value = "/doc") public class DocumentController { private static final Logger LOG = Logger.getLogger(DocumentController.class); @Autowired DocumentService documentService; @RequestMapping(value = "/upload", method = RequestMethod.POST) public @ResponseBody ResponseMetadata handleFileUpload(@RequestParam(value="file") MultipartFile file) throws IOException { return documentService.save(file); } @RequestMapping(value = "/{id}", method = RequestMethod.GET) public HttpEntitygetDocument(@PathVariable Long id) { HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.setContentType(MediaType.IMAGE_JPEG); return new ResponseEntity (documentService.getDocumentFile(id), httpHeaders, HttpStatus.OK); } @RequestMapping(method = RequestMethod.GET) public @ResponseBody List getDocument() { return documentService.findAll(); } }
Defining Document Model Class
Document.java@Entity public class Document { @Id @GeneratedValue(strategy= GenerationType.IDENTITY) private Long id; @Column private String docName; @Column @Lob private byte[] file; //getters and setters goes here
Other Interesting Posts Spring Boot Angular Deployment Spring Boot MVC Apache Tiles Spring Boot Actuator Rest Endpoints Example Spring MVC Pdf Excel View Resolver Example Spring Boot Thymeleaf Example Spring Boot Security Hibernate Example with complete JavaConfig Securing REST API with Spring Boot Security Basic Authentication Spring Boot Security Password Encoding using Bcrypt Encoder Spring Security with Spring MVC Example Using Spring Boot Websocket spring Boot Integration Without STOMP with complete JavaConfig
Service Implementation
DocumentServiceImpl.java@Service public class DocumentServiceImpl implements DocumentService { @Autowired private DocumentDao documentDao; @Override public ResponseMetadata save(MultipartFile file) throws IOException { Document doc = new Document(); doc.setDocName(file.getOriginalFilename()); doc.setFile(file.getBytes()); documentDao.save(doc); ResponseMetadata metadata = new ResponseMetadata(); metadata.setMessage("success"); metadata.setStatus(200); return metadata; } @Override public byte[] getDocumentFile(Long id) { return documentDao.findOne(id).getFile(); } @Override public ListfindAll() { return (List ) documentDao.findAll(); } }
Rest of the server implementation are common codes which can be found in the source code below. Now let us move to client side.
Client Side Implementation
We have a simple .html file having a input type as file and a bootstrap table to display the uploaded file. It can be found in the source code. Let us take a look into our angular controller implementation.
The controller implementation is a very simple. We have one directive defined as fileModel that is responsible to set the uploaded file in a $scope variable. Rest of the implementation is very common. It has methods defined that is responsible for calling angular service methods which makes REST call to upload the document and read the document.
app.jsApp.controller('docController', ['$scope', '$rootScope','docService','$http', function($scope, $rootScope, docService, $http) { $scope.file = ''; $scope.upload = function(){ var file = $scope.file; docService.saveDoc(file) .then( function (response) { alert("file uploaded successfully."); $http.get("http://localhost:8080/doc/").success( function(response) { $rootScope.docList = response; }); }, function (errResponse) { } ); } } ]); App.constant('urls', { DOC_URL: 'http://localhost:8080/doc/' }); App.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]); }); }); } }; } ]); App.run(function($rootScope, $http) { $http.get("http://localhost:8080/doc/").success( function(response) { $rootScope.docList = response; }); });
Defining Angular Service
DocumentService.js'use strict'; var App = angular.module('uploadApp',[]); App.factory('docService', ['$http', '$q', 'urls', function ($http, $q, urls) { var factory = { saveDoc: saveDoc, findDoc: findDoc }; return factory; function saveDoc(file) { var deferred = $q.defer(); var formData = new FormData(); formData.append('file', file); $http.post(urls.DOC_URL+'upload', formData,{ transformRequest : angular.identity, headers : { 'Content-Type' : undefined }}) .then( function (response) { deferred.resolve(response.data); }, function (errResponse) { alert(errResponse.data.errorMessage); deferred.reject(errResponse); } ); return deferred.promise; }; function findDoc(docId) { var deferred = $q.defer(); $http.get(urls.DOC_URL + '/'+docId) .then( function (response) { deferred.resolve(response.data); }, function (errResponse) { alert(errResponse.data.errorMessage); deferred.reject(errResponse); } ); return deferred.promise; } } ]);
And finally, following is our html page where we have used the file-model directive.
<html ng-app="uploadApp"> <head> <meta charset="utf8" /> <title>Document Upload</title> <link rel="stylesheet" href="styles/bootstrap.min.css"> </head> <body ng-controller="docController"> <div class="container"> <div class="col-md-6"> <div class="row"> <h2>Upload Document</h2> <table class="table table-bordered"> <tr> <td><input type="file" class="custom-file-input" file-model="file"></td> </tr> <tr> <td><button ng-click="upload()">Upload</button></td> </tr> </table> </div> <div class="row"> <table class="table table-bordered"> <thead> <tr> <th>File Name</th> <th>Action</th> </tr> </thead> <tbody> <tr ng-repeat="doc in docList"> <td><a href="/doc/{{doc.id}}">{{doc.docName}}</a></td> <td><a href="/doc/{{doc.id}}" target="_blank">Download</a></td> </tr> </tbody> </table> </div> </div> </div> <script src="lib/plugin/jquery-2.2.1.min.js"></script> <script src="lib/plugin/bootstrap.min.js"></script> <script src="lib/plugin/angular.min.js"></script> <script src="documentService.js"></script> <script src="app.js"></script> </body> </html>
Conclusion
I hope this article served you that you were looking for. If you have anything that you want to add or share then please share it below in the comment section.