Click here to Skip to main content
13,764,745 members
Click here to Skip to main content
Add your own
alternative version

Stats

138.9K views
6.5K downloads
24 bookmarked
Posted 21 Feb 2015
Licenced CPOL

File Upload Using AngularJS and ASP.NET MVC5

, 21 Feb 2015
Rate this:
Please Sign up or sign in to vote.
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:

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.

(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

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

template

<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

"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)

"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

[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.

<input type="file" name="attachment" class="form-control" 

data-ak-file-model="tutorial.attachment" multiple />

In akFileUploader module, update the getModelAsFormData of akFileUploaderService.

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.

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

Write the above line instead of following in akFileModel directive:

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

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

[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)

Share

About the Author

Atish Dipongkor
Software Developer BrainStation-23
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.

You may also be interested in...

Pro

Comments and Discussions

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

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web01-2016 | 2.8.181113.4 | Last Updated 21 Feb 2015
Article Copyright 2015 by Atish Dipongkor
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid