AngularJS Custom Directive[Upload File]

In my previous post, I just showed you how to create a simple Angular JS directive.In this post, we will see how to upload a file using Angular JS as front end and Spring MVC as backend. We will upload the file and along with the file we will send some other information too. So, lets start.

Step 1. POM update.

We will be needing some extra lib dependencies in our project. So lets add the dependencies. I am posting here the whole pom.xml. Here the commons-fileupload and commons-io are responsible for file upload.

<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.anupam</groupId>
	<artifactId>AngularSpring</artifactId>
	<packaging>war</packaging>
	<version>0.0.1-SNAPSHOT</version>
	<name>AngularSpring Maven Webapp</name>
	<url>http://maven.apache.org</url>
	<dependencies>
		<!-- Spring -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>4.2.2.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-beans</artifactId>
			<version>4.2.2.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>4.2.2.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>4.2.2.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-tx</artifactId>
			<version>4.2.2.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
			<version>4.2.2.RELEASE</version>
		</dependency>
		<!-- Hibernate -->
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-core</artifactId>
			<version>4.3.7.Final</version>
		</dependency>
		<!-- MySQL -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.33</version>
		</dependency>
		<dependency>
			<groupId>commons-dbcp</groupId>
			<artifactId>commons-dbcp</artifactId>
			<version>1.2.2</version>
		</dependency>
		<!-- Jackson -->
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-core</artifactId>
			<version>2.6.3</version>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>2.6.3</version>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-annotations</artifactId>
			<version>2.6.3</version>
		</dependency>
		<!-- Apache File Upload -->
		<dependency>
			<groupId>commons-fileupload</groupId>
			<artifactId>commons-fileupload</artifactId>
			<version>1.2.2</version>
		</dependency>
		<dependency>
			<groupId>commons-io</groupId>
			<artifactId>commons-io</artifactId>
			<version>2.4</version>
		</dependency>

		<!-- Testing -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>4.2.2.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.mockito</groupId>
			<artifactId>mockito-core</artifactId>
			<version>2.0.31-beta</version>
		</dependency>

	</dependencies>
	<build>
		<finalName>AngularSpring</finalName>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>


Step 2. Spring config. WEB-INF/spring/app-config.xml

Now, we will need to inject the following multipart resolver in the spring app configuration. Please read this amazing documentation about Spring File Upload.The complete configuration file looks like as shown below.

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd">


	<!-- Annotation scan -->
	<context:annotation-config />
	<context:component-scan base-package="com.anupam.*" />

	<!-- MVC -->
	<mvc:annotation-driven />

	<!-- Multi Part -->
	<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />

</beans>

Step 3. Now we will add a method to handle the request in our PostController.java class

package com.anupam.controller;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import com.anupam.dao.PostDAO;
import com.anupam.dao.UserDAO;
import com.anupam.uivo.PostUiVO;
import com.anupam.vo.TbPostVO;
import com.anupam.vo.TbUserVO;

@Controller
public class PostController
{
    @Autowired
    private PostDAO postDAO;

    @Autowired
    private UserDAO userDAO;

    @RequestMapping("/hello")
    @ResponseBody
    public TbUserVO sayHello()
    {
	TbUserVO user = new TbUserVO();
	user.setFirstName("Anupam");
	user.setLastName("Gogoi");
	return user;
    }

    @RequestMapping(path = "/list", method = RequestMethod.GET)
    @ResponseBody
    public List<PostUiVO> getPostByUser()
    {
	List<PostUiVO> listPost = new ArrayList<>();
	try
	{
	    List<TbPostVO> list = postDAO.getPostByUser(1);
	    if (list != null && !list.isEmpty())
	    {
		for (TbPostVO p : list)
		{
		    listPost.add(new PostUiVO(p.getPostID(), p.getScrap(), p.getDate(), p.getUserVO().getEmail()));
		}
	    }
	}
	catch (Exception e)
	{
	    e.printStackTrace();
	}

	return listPost;
    }

    @RequestMapping(path = "/save", method = RequestMethod.POST)
    @ResponseBody
    public List<PostUiVO> savePost(
	    @RequestBody Map<String, Object> values) throws Exception
    {
	System.out.println("Received " + values.get("scrap"));
	String scrap = values.get("scrap").toString();

	TbPostVO postVO = new TbPostVO();
	postVO.setScrap(scrap);
	postVO.setDate(new Date());
	postVO.setUserVO(userDAO.getUserByID(1));
	postDAO.savePost(postVO);
	return getPostByUser();
    }

    @RequestMapping(path = "/remove/{id}", method = RequestMethod.DELETE)
    @ResponseBody
    public List<PostUiVO> deletePost(
	    @PathVariable("id") Integer postID) throws Exception
    {
	postDAO.deletePost(postDAO.getPostByID(postID));
	return getPostByUser();
    }

    @RequestMapping(path = "/upload", method = RequestMethod.POST)
    @ResponseBody
    public String uploadFile(@RequestParam(name="scrap")Object scrap, @RequestParam(name = "file") MultipartFile file) throws Exception
    {
	System.out.println(scrap.toString()+" Size "+file.getSize());
	// Add necessary codes here to save file or whatever else.
	return "";
    }
}

The method uploadFile() does the necessary tricks.

Step 4. Now lets modify our Angular scripts. Here goes the main.script.

var coreApp = angular.module("coreApp", []);

coreApp.directive('fileUpload', function()
{
	return {
	scope : false,
	link : function(scope, elem, attr)
	{
		elem.on('change', function(event)
		{
			var file = event.target.files[0];
			scope.$apply(function()
			{
				scope.data.file = file;
			});

		});
	}
	}
});
coreApp.service('PostService', function($http)
{

	// Upload file data.
	this.uploadFile = function(formData, onSaved)
	{

		$http.post('post/upload', formData, {
		transformRequest : angular.identity,
		headers : {
			'Content-Type' : undefined
		}
		}).success(function()
		{
			onSaved(data);
		}).error(function()
		{
		});
	};

});
coreApp.controller('myController', function($scope, PostService)
{
	$scope.data = {
	scrap : 'Some data',
	file : null
	};

	$scope.doSubmit = function()
	{
		var formData = new FormData();
		formData.append("scrap", $scope.data.scrap);
		formData.append("file", $scope.data.file);

		PostService.uploadFile(formData, function(data)
		{
			alert('uploaded...');
		});
	};

});

Step 5. The Html page, upload.html

<html>
<head>
<title>Angular JS Directive.</title>
<script src="js/angular.min.js"></script>
<script src="js/main.js"></script>
</head>

<body ng-app="coreApp" ng-controller="myController">

<h2>AngularJS Sample Application</h2>


<div>

<form ng-submit="doSubmit()">
			Uploader:<input type="text" ng-model="data.scrap" /> 
 Image: <input type="file" file-upload /> 
</br> <input type="submit" value="Submit" />
		</form>


	</div>

	
</body>
</html>

Okay, all done. In the next post, we will modify our Monkey App. See you soon.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s