File Upload with AngularJs And Spring Boot Rest

By Dhiraj Ray, 02 October,2017   7K

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.

Project Structure

Following is the project structure which we will be creating.

spring-boot-angular-file-upload-strct

Following is the final output of what we will be implementing here.

spring-boot-angular-file-upload

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.

pom.xml
<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 HttpEntity getDocument(@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 List findAll() {
        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.js
App.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.

Download the source

Further Reading on Spring Boot

1. File Upload Angularjs Spring Boot Rest

2. Spring Mvc Angularjs Integration Example

3. Spring Boot Mvc Apache Tiles Example

4. Spring Mvc Contentnegotiating Viewresolver Example

5. Spring Boot Multiple Database Configuration

If You Appreciate What We Do Here On Devglan, You Should Consider:

References

Angular Spring Boot File Upload

Spring Boot

W3 Schools Angular