Click here to Skip to main content
15,887,267 members
Articles / Web Development / HTML
Tip/Trick

File Upload Using AngularJS and ASP.NET MVC5

Rate me:
Please Sign up or sign in to vote.
4.79/5 (18 votes)
21 Feb 2015CPOL2 min read 209K   7.1K   24   46
How to upload file using AngularJS and ASP.NET MVC5? How to upload multiple files using AngularJs and MVC5?

What's This?

The goal of this is as given in the title. It's very simple. Here, I will document the simplest way to upload file using AngularJs and ASP.NET MVC5.

Why is This?

There are so many libraries to do this online. So, what difference will I make? If this question comes to your mind at the very beginning, then cool! Let's have a look at why you must be bothered about this.

My requirement is very simple. I have a Model. Please see below:

C#
public class TutorialModel
    {
        public string Title { get; set; }
        public string Description { get; set; }
        public HttpPostedFileBase Attachment { get; set; }
    }

I want to bind this model from client side with Angular and post it to the ASP.NET MVC5 controller.

Most of the libraries that I found online work in the following way:

  1. Upload file --> Save it --> Return the file URL in response
  2. Send another request with model and file URL

The common problem of this way is: every time you change the file, it will upload the file to the server. Previous files will not be deleted. So I don't want to do this and maybe even you might not want it. I will show how we can do it in one request. Users are free to change anything as many times as they wish. When they will click save, then the Model will be sent to the server.

Form

How is This?

To do this, I will use HTML5 FormData here. I have written a separate Angular module for this so that anyone can use it in their module. Let's have a look in my akFileUploader module.

Download from github.

JavaScript
(function () {

    "use strict"

    angular.module("akFileUploader", [])

           .factory("akFileUploaderService", ["$q", "$http",
               function ($q, $http) {

                   var getModelAsFormData = function (data) {
                       var dataAsFormData = new FormData();
                       angular.forEach(data, function (value, key) {
                           dataAsFormData.append(key, value);
                       });
                       return dataAsFormData;
                   };

                   var saveModel = function (data, url) {
                       var deferred = $q.defer();
                       $http({
                           url: url,
                           method: "POST",
                           data: getModelAsFormData(data),
                           transformRequest: angular.identity,
                           headers: { 'Content-Type': undefined }
                       }).success(function (result) {
                           deferred.resolve(result);
                       }).error(function (result, status) {
                           deferred.reject(status);
                       });
                       return deferred.promise;
                   };

                   return {
                       saveModel: saveModel
                   }}])
         .directive("akFileModel", ["$parse",
                function ($parse) {
                    return {
                        restrict: "A",
                        link: function (scope, element, attrs) {
                            var model = $parse(attrs.akFileModel);
                            var modelSetter = model.assign;
                            element.bind("change", function () {
                                scope.$apply(function () {
                                    modelSetter(scope, element[0].files[0]);
                                });
                            });
                        }
                    };
                }]);
})(window, document);

I will give you a very brief description of what this module does. It has one directive and one factory service.

  • akFileModel directive: It is responsible for changing file and binding it to the modelSetter.
  • akFileUploaderService: It basically creates FormData objects and sends it to the desired URL using $http.

Use in MVC

application.js

JavaScript
"use strict";
(function () {
    angular.module("application", ["ngRoute", "akFileUploader"]);
})();

template

HTML
<form class="form-horizontal">
    <h4>Tutorial</h4>
    <hr />
    <div class="form-group">
        <label for="title" class="col-md-2 control-label">Title</label>
        <div class="col-md-10">
            <input type="text" data-ng-model="tutorial.title" 
            name="title" class="form-control" />
        </div>
    </div>
   <div class="form-group">
        <label for="description" class="col-md-2 control-label">Description</label>
        <div class="col-md-10">
            <textarea data-ng-model="tutorial.description" 
            name="description" class="form-control">
            </textarea>
        </div>
    </div>
   <div class="form-group">
        <label for="attachment" class="col-md-2 control-label">Attachment</label>
        <div class="col-md-10">
            <input type="file" name="attachment" 
            class="form-control" data-ak-file-model="tutorial.attachment" />
        </div>
    </div>
  <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="button" class="btn btn-primary" 
            value="Save" data-ng-click="saveTutorial(tutorial)" />
        </div>
    </div>
</form>

service

JavaScript
"use strict";
(function () {
    angular.module("application")
           .factory("entityService", 
           ["akFileUploaderService", function (akFileUploaderService) {
               var saveTutorial = function (tutorial) {
                   return akFileUploaderService.saveModel(tutorial, "/controllerName/actionName");
               };
               return {
                   saveTutorial: saveTutorial
               };
           }]);
})();

controller(js)

JavaScript
"use strict";
(function () {
    angular.module("application")
           .controller("homeCtrl", ["$scope", "entityService",
               function ($scope, entityService) {
                   $scope.saveTutorial = function (tutorial) {
                       entityService.saveTutorial(tutorial)
                                    .then(function (data) {
                                        console.log(data);
                                    });
                   };
               }]);
})();

MVC Controller Action

C#
[HttpPost]
public ActionResult SaveTutorial(TutorialModel tutorial)
    {
        return Json("Tutorial Saved",JsonRequestBehavior.AllowGet);
    }

Uploading Multiple files

In order to upload multiple files, You have to change something. In input field, allow multiple.

HTML
<input type="file" name="attachment" class="form-control" 
data-ak-file-model="tutorial.attachment" multiple />

In akFileUploader module, update the getModelAsFormData of akFileUploaderService.

JavaScript
var getModelAsFormData = function (data) {
                       var dataAsFormData = new FormData();
                       angular.forEach(data, function (value, key) {
                           if (key == "attachment") {
                               console.log(value);
                               for (var i = 0; i < value.length; i++) {
                                   dataAsFormData.append(value[i].name, value[i]);
                               }
                           } else {
                               dataAsFormData.append(key, value);
                           }
                       });
                       return dataAsFormData;
                   };

Here, I have appended all files in form data by attachment key. You will notice that my input name is attachment. So if you change it, then keep the same name in getModelAsFormData as well.

JavaScript
modelSetter(scope, element[0].files);

Write the above line instead of following in akFileModel directive:

JavaScript
modelSetter(scope, element[0].files[0]);

Now receive the files in controller in the following way...

C#
[HttpPost]
       public ActionResult SaveTutorial(TutorialModel tutorial)
       {
           foreach (string file in Request.Files)
           {
               var fileContent = Request.Files[file];
               if (fileContent != null && fileContent.ContentLength > 0)
               {
                   var inputStream = fileContent.InputStream;
                   var fileName = Path.GetFileName(file);
                   var path = Path.Combine(Server.MapPath("~/App_Data/Images"), fileName);
                   using (var fileStream = System.IO.File.Create(path))
                   {
                       inputStream.CopyTo(fileStream);
                   }
               }
           }
           return Json("Tutorial Saved",JsonRequestBehavior.AllowGet);
       }

So I am done. Start using it. Thanks!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Instructor / Trainer Jashore University of Science and Technology
Bangladesh Bangladesh
2016 Microsoft MVP

Currently, I am devoted to provide technical and development support to the SharePoint clients and also I am working on angularjs. I am experienced with C#, ASP.NET, SharePoint, SignalR, angularjs, MS SQL, Oracle 11g R2, Windows Phone, Firefox OS and so on. I have fallen in love with many technologies but never got married to any of them. I am evolving myself as full stack developer. I always like to share knowledge as much as to gather from you.

Comments and Discussions

 
QuestionSave files to local folder Pin
Klent Diamond1-Jan-18 16:20
Klent Diamond1-Jan-18 16:20 
QuestionThank you! It work for me. Can someone recommend me "ng packages" who do this also? Pin
blaskxx28-Mar-17 6:32
blaskxx28-Mar-17 6:32 
QuestionThe Demo can't run Pin
Member 1287564130-Nov-16 16:15
Member 1287564130-Nov-16 16:15 
AnswerRe: The Demo can't run Pin
Atish Dipongkor1-Dec-16 23:56
professionalAtish Dipongkor1-Dec-16 23:56 
QuestionUpload File using Angular JS Pin
Member 1260705327-Jun-16 18:08
Member 1260705327-Jun-16 18:08 
AnswerRe: Upload File using Angular JS Pin
Atish Dipongkor28-Jun-16 1:13
professionalAtish Dipongkor28-Jun-16 1:13 
GeneralRe: Upload File using Angular JS Pin
Member 1260705328-Jun-16 19:06
Member 1260705328-Jun-16 19:06 
QuestionUsing this we can able to upload more than 2 gb file (any extension) Pin
Member 822666524-Jun-16 5:14
Member 822666524-Jun-16 5:14 
QuestionURL? Pin
Member 1259426220-Jun-16 8:44
Member 1259426220-Jun-16 8:44 
AnswerRe: URL? Pin
Atish Dipongkor20-Jun-16 20:28
professionalAtish Dipongkor20-Jun-16 20:28 
GeneralRe: URL? Pin
Member 1259426221-Jun-16 2:00
Member 1259426221-Jun-16 2:00 
QuestionYou don't need file stream Pin
Aximili15-Jun-16 15:34
professionalAximili15-Jun-16 15:34 
AnswerRe: You don't need file stream Pin
Atish Dipongkor16-Jun-16 1:24
professionalAtish Dipongkor16-Jun-16 1:24 
QuestionFile not get in webapi Pin
puneet kankar3-Feb-16 19:09
puneet kankar3-Feb-16 19:09 
AnswerRe: File not get in webapi Pin
Atish Dipongkor3-Feb-16 19:53
professionalAtish Dipongkor3-Feb-16 19:53 
QuestionNullable decimal properties don't validate Pin
Member 1175819923-Jan-16 6:18
Member 1175819923-Jan-16 6:18 
QuestionGetting Error as Unsupported Media Content Pin
magesh venkatesan16-Jan-16 17:16
magesh venkatesan16-Jan-16 17:16 
AnswerRe: Getting Error as Unsupported Media Content Pin
Atish Dipongkor17-Jan-16 1:21
professionalAtish Dipongkor17-Jan-16 1:21 
GeneralRe: Getting Error as Unsupported Media Content Pin
magesh venkatesan18-Jan-16 5:11
magesh venkatesan18-Jan-16 5:11 
GeneralRe: Getting Error as Unsupported Media Content Pin
Atish Dipongkor18-Jan-16 18:59
professionalAtish Dipongkor18-Jan-16 18:59 
QuestionAnother model data along with this file list Pin
Md._Mehedi_Hasan4-Nov-15 1:45
professionalMd._Mehedi_Hasan4-Nov-15 1:45 
AnswerRe: Another model data along with this file list Pin
Atish Dipongkor4-Nov-15 3:16
professionalAtish Dipongkor4-Nov-15 3:16 
GeneralRe: Another model data along with this file list Pin
Md._Mehedi_Hasan6-Nov-15 2:56
professionalMd._Mehedi_Hasan6-Nov-15 2:56 
QuestionGetting error while upload large file Pin
Member 105711068-Sep-15 23:58
Member 105711068-Sep-15 23:58 
AnswerRe: Getting error while upload large file Pin
Atish Dipongkor9-Sep-15 0:39
professionalAtish Dipongkor9-Sep-15 0:39 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.