Sending Uploaded File Information In A CORS Enabled Web Application

In this blog, let’s see

What are Directives in AngularJS?

  • Actually, they're markers on DOM elements.
  • With the help of Directives, we can extend HTML with the new attributes.

There are already several predefined directives but also apart from that, we can also create our own Directive as well.

Let us see how to create our own Directive.

We will learn how to create our own Directive to upload the file and with the help of this, we will upload MS-Excel file and will be going to process this at WebAPI controller.

In order to do this,

We need to perform the steps given below.

Step 1

Add Directive given below in your controller.js. Directive is with name ngFileToSelect. The code snippet is given below to do it.

  1. app.directive("ngFileToSelect"function () {  
  2.     return {  
  3.         link: function ($scope, ele) {  
  4.             ele.bind("change"function (e) {  
  5.                 $scope.file = (e.srcElement || e.target).files[0];  
  6.                 $scope.filePath = e.target.value;  
  7.                 $scope. getFileInfo ();  
  8.             })  
  9.         }  
  10.     }  
  11. })  
Step 2

Now, let us see how to apply this Directive to your HTML. 

The code snippet is given below for it.
  1. <div class="panel-body padding-10">  
  2.             <div class="form-inline" id="fileupload">  
  3.                 <div class="form-group">  
  4.                     <label class="margin-right-label">File Name:</label>  
  5.                     <div class="input-group">  
  6.                         <input type="text" class="form-control" ng-model="filePath" ng-file-select="onFileSelect($files)" ng-disabled="isBrowseDisabled">  
  7.                         <label class="input-group-btn">  
  8.                             <span class="btn btn-primary">  
  9.                                 Browse <input type="file" style="display: none;" ng-file-Toselect="onFileSelect($files)" ng-disabled="isBrowseDisabled">  
  10.                             </span>  
  11.                         </label>  
  12.                     </div>  
  13.                 </div>  
  14.             </div>  
  15.             <label class="margin-right-label">{{fileInfo}}</label>  
  16.         </div>  
  17.   
  18. <div class="modal-footer">  
  19.     <button class="btn btn-primary" type="button" ng-click="upload();" >Upload</button>  
  20. </div>  
Now, your HTML looks, as shown below.



Step 3

Now, in your controller.js, write the code, as shown below.
  1. angular.module("SandipModule").controller("FileUploadController", ["$scope""$uibModalInstance"function ($scope, $uibModalInstance) {  
  2.   
  3.   
  4.     $scope.onLoad = function (reader, deferred, scope) {  
  5.         return function () {  
  6.             scope.$apply(function () {  
  7.                 deferred.resolve(reader.result);  
  8.             });  
  9.         };  
  10.     };  
  11.   
  12.     $scope.onError = function (reader, deferred, scope) {  
  13.         return function () {  
  14.             scope.$apply(function () {  
  15.                 deferred.reject(reader.result);  
  16.             });  
  17.         };  
  18.     };  
  19.   
  20.     $scope.onProgress = function (reader, scope) {  
  21.         return function (event) {  
  22.             scope.$broadcast("fileProgress",  
  23.                 {  
  24.                     total: event.total,  
  25.                     loaded: event.loaded  
  26.                 });  
  27.         };  
  28.     };  
  29.   
  30.    $scope.getReader = function (deferred, scope) {  
  31.         var reader = new FileReader();  
  32.         reader.onload = $scope.onLoad(reader, deferred, scope);  
  33.         reader.onerror = $scope.onError(reader, deferred, scope);  
  34.         reader.onprogress = $scope.onProgress(reader, scope);  
  35.         return reader;  
  36.     };  
  37.   
  38.    $scope.readAsDataURL = function (file, scope) {  
  39.         var deferred = $q.defer();  
  40.         var reader = $scope.getReader(deferred, scope);  
  41.         reader.readAsDataURL(file);  
  42.         return deferred.promise;  
  43.     };  
  44.   
  45.    $scope.xslFinaldata = null;  
  46.    $scope.fileInfo = "";  
  47.    $scope.fileInfodetails == "";  
  48.    $scope.data = uploadaccessData;  
  49.   
  50.    $scope.upload = function () {   
  51.        $scope.xslFinaldata = $scope.xslData;  
  52.        var docContent = $scope.xslFinaldata;  
  53.         $scope.fileName = $scope.uploadedDocName;  
  54.         var fileName = $scope.fileName;  
  55.         $scope.fileInfo = $scope.fileInfodetails;  
  56.   
  57.         var promisePost = myService.ProcessUploadedDocument(JSON.stringify(fileName), JSON.stringify(docContent));  
  58.         promisePost.then(function (response) {  
  59.             $scope.SuccessMessage = response;  
  60.         }, function (err) {  
  61.         });  
  62.     }  
  63.   
  64.     $scope.xslData = "";  
  65.     $scope.uploadedDocName = "";  
  66.   
  67.     $scope.getFileInfo = function () {  
  68.         $scope.progress = 0;  
  69.         $scope.readAsDataURL($scope.file, $scope)  
  70.                       .then(function (result) {  
  71.                           $scope.xslData = result;  
  72.                           $scope.uploadedDocName = $scope.file.name;  
  73.                           $scope.fileInfodetails = "File name: " + $scope.filePath + " " + $scope.file.size + "   " + "Bytes";  
  74.                                                 });  
  75.     };  
  76.   
  77. }]);  
Code explanation->

When the user selects an Excel document to upload at that time, the method given below is getting invoked with the help of our directive.
  1. $scope.getFileInfo();  
Through this method, we are going to retrieve all file information, as shown below.
  1. Size of file
  2. File Name.
  3. File Contents

Now, on Upload button, click

$scope.upload() Method is getting executed through which we are going to post file details to ProcessUploadedDocument method in myService, which is an Angular Service

The line of code given below demonstrates it.

  1. var promisePost = myService.ProcessUploadedDocument(JSON.stringify(fileName), JSON.stringify(docContent));  
  2. promisePost.then(function (response) {  
  3.     $scope.SuccessMessage = response;  
  4. }, function (err) {  
  5. });  
Note, here docContent are in binary format.

Step 4

In service.js

The code snippet is given below for service.js,
  1. myService.ProcessUploadedDocument = function ( fileName, docContent) {  
  2.        var def = $q.defer();  
  3.        var request = $http({  
  4.            url: localhost:85789 + "/api/MyInfoImport/ProcessUploadedDocument",  
  5.            dataType: 'json',  
  6.            method: 'POST',  
  7.            data: JSON.stringify({'fileName': fileName, 'docContent': docContent})  
  8.        }).success(function (data, status, headers, config) {  
  9.            def.resolve(data);  
  10.        }).error(function (response, status, headers, config) {  
  11.            console.log(response);  
  12.        });  
  13.        return def.promise;  
  14.    }  
Code explanation->

Now, we need to invoke WebAPI controller action. 

The line of code demonstrates it.
  1. var request = $http({  
  2.             url: localhost:85789 + "/api/MyInfoImport/ProcessUploadedDocument",  
  3.             dataType: 'json',  
  4.             method: 'POST',  
  5.               
  6.         })  
Here, ProcessUploadedDocument Web API controller action is getting invoked.

With two parameters to it, the line of code demonstrates how to pass two parameters to Web API controller action
  1. data: JSON.stringify({'fileName': fileName, 'docContent': docContent})  
Step 5

We are invoking WebAPI Controller action with the multiple parameters from the client side in CORS enabled Web Application.

We can’t invoke WebAPI Controller action with more than one parameter in CORS enabled Web Applications, as per default behavior.

Hence, remember 

To install WebAPI CORS MULTI PARAMS MODELBINDER NuGet package.

For installation of NuGet package given above, run the command given below in the Package Manager console.

PM>Install-Package WebAPICORSMULTIPARAMSMODELBINDER


Install this package in your WebAPI Controller.

The code snippet for WebAPI Controller MyInfoImportController.cs is given below.
  1. [HttpPost, WebAPICORSMULTIPOSTPARAMS.MultiPostParamsBinding.MultiPostParams]  
  2.         [Route("ProcessUploadedDocument")]  
  3.         public HttpResponseMessage ProcessUploadedDocument( string fileName, string docContent)  
  4.         {  
  5.              
  6.             HttpResponseMessage resp;  
  7.             Microsoft.Office.Interop.Excel.Application oExcel = null;  
  8.             Workbook oWorkBook = null;  
  9.             Worksheet oWorkSheet = null;  
  10.             Range oRange = null;  
  11.             string fName = Newtonsoft.Json.JsonConvert.DeserializeObject<string>(fileName).ToLower();  
  12.             string fContent = Newtonsoft.Json.JsonConvert.DeserializeObject<string>(docContent);  
  13.                string uploadPath = System.Web.Hosting.HostingEnvironment.MapPath(@"~/MyFileFolder/Uploads");  
  14.   
  15.                     fContent = fContent.Replace("data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,", String.Empty);  
  16.                     byte[] fileData = Convert.FromBase64String(fContent);  
  17.                      
  18.                         string createFPath=String.Concat(uploadPath,"/");  
  19.                         string filename = createFPath+  fName;  
  20.                         Stream stream = new MemoryStream(fileData);  
  21.                         using (Stream file = File.Create(filename))  
  22.                         {  
  23.                             stream.CopyTo(file);  
  24.                         }  
  25.   
  26.   
  27.                         ResponseData result = imageService.UpdateChargeImport(fileData);  
  28.   
  29.                         if (System.IO.File.Exists(createFPath)) System.IO.File.Delete(createFPath);  
  30.                             GC.Collect();  
  31.                 resp = Request.CreateResponse<string>(HttpStatusCode.OK, strResponse);  
  32.             return resp;  
  33.         }  
Code explanation->

Note

In the code snippet given above.

The line of code given below is to demonstrate how to add an attribute on WebAPI controller Action in order to invoke it with the multiple parameters.

  • [HttpPost, WebAPICORSMULTIPOSTPARAMS.MultiPostParamsBinding.MultiPostParams]

  • The line of code is to demonstrate how to set the upload path
    string uploadPath = System.Web.Hosting.HostingEnvironment.MapPath(@"~/MyFileFolder/Uploads");

  • Here, we used HostingEnvironment.MapPath instead of Server.MapPath, as we are using this into the WebAPI Controller .

Now, we need to set docContent,

  • The line of code is given below demonstrate
    1. string fContent = Newtonsoft.Json.JsonConvert.DeserializeObject<string>(docContent);  
    Now, in order process this

  • The line of code indicates that we are going to process uploaded Excel file by removing unnecessary content
    1. fContent = fContent.Replace("data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,", String.Empty);  
  • The line of code given below demonstrates how to convert this uploaded document to byte array.
    1. byte[] fileData = Convert.FromBase64String(fContent);  
  • The line of code demonstrates how to create a replica of your uploaded document into your application folder
    i.e. at uploadPath,
    1. string createFPath=String.Concat(uploadPath,"/");  
    2.                         string filename = createFPath+  fName;  
    3.                         Stream stream = new MemoryStream(fileData);  
    4.                         using (Stream file = File.Create(filename))  
    5.                         {  
    6.                             stream.CopyTo(file);  
    7.                         }  
    Here, actually we added an uploaded document at uploadPath mentioned above.

  • Now, we can send this byte array to WCF Service as well for processing

    The line of code given below demonstrates it.
    1. ResponseData result = imageService.UpdateChargeImport(fileData);  
    Here, imageService is our WCF service instance.

  • The line of code given below demonstrates how to delete the file from the uploaded path. 
    1. if (System.IO.File.Exists(createFPath))   
    2. {  
    3.     System.IO.File.Delete(createFPath);  
    4. }