How to upload file using AngularJS

This post shows you how to upload a file in AngularJS with ASP.NET Web API.

As you know, angularjs file upload is an indispensable feature in web applications.

However, if you are uploading files using web api in the AngularJS you need to use the library for the AngularJS or use the directive to resolve the problem HttpPostedFileBase is always null when doing HttpPost.

You need to create the Web API method lets you to upload files to your IIS server.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Invoice.Controllers
{
    [Authorize]
    public class UploadController : Controller
    {
        [HttpPost]
        public JsonResult File(HttpPostedFileBase file)
        {
            string path = HttpContext.Server.MapPath($"~/bin/Files");
            if (!Directory.Exists(path))
                Directory.CreateDirectory(path);
            if (file != null && file.ContentLength > 0)
            {
                if (!System.IO.File.Exists($"{path}/{file.FileName}"))
                {
                    file.SaveAs(Path.Combine(path, Path.GetFileName(file.FileName)));
                    return Json(new { filename = file.FileName });
                }
                return Json(new { filename = "exist" });
            }
            return Json(new { filename = "null" });
        }
    }
}

If we upload the file successfully we will return the file name, otherwise it will be 'null' or 'exist' if the file already exists on the server.

To upload file in AngularJS, you should install the angularjs file upload, then include to your shared layout or index.html

using System.Web;
using System.Web.Optimization;

namespace Invoice
{
    public class BundleConfig
    {
        // For more information on bundling, visit https://go.microsoft.com/fwlink/?LinkId=301862
        public static void RegisterBundles(BundleCollection bundles)
        {           
            //...

            bundles.Add(new ScriptBundle("~/main/js").Include(                
                "~/Scripts/angular.min.js",
                "~/Scripts/angular-route.min.js",
                "~/Scripts/angular-ui/ui-bootstrap-tpls.min.js",
                "~/Scripts/angular-animate.min.js",
                "~/Scripts/toaster.min.js",
                "~/Scripts/ng-file-upload.js",
                "~/Scripts/ng-file-upload-shim.js",
                "~/app/app.js",
                "~/app/controllers/invoiceTemplateController.js"));
        }
    }
}

You can install ng-file-upload.js from Manage Nuget Packages in your visual studio or you can download it directly from https://github.com/danialfarid/ng-file-upload, then create a controller to upload file in AngularJS as shown below.

(function () {
    'use strict';

    angular
        .module('app')
        .controller('invoiceTemplateController', invoiceTemplateController);

    invoiceTemplateController.$inject = ['$scope', '$uibModal', 'toaster', 'Upload'];

    function invoiceTemplateController($scope, $modal, toaster, Upload) {

        $scope.upload = function (file) {
            if (file === undefined) {
                toaster.error('Error', 'Please select your file to upload!');
                return;
            }
            Upload.upload({
                url: '/Upload/File',
                method: 'POST',
                data: { file: file }
            }).then(function (response) {
                if (response.data.filename === 'null') {
                    toaster.error('Error', 'Your upload file is invalid!');
                    return;
                }
                if (response.data.filename === 'exist') {
                    toaster.error('Error', 'Your upload file already exists on the server!');
                    return;
                }
                var fileName = response.config.data.file.name;
            }, function (error) {
                toaster.error("Error", error.status);
            }, function (evt) { });
        };

        $scope.fileUpload = function (invoiceTemplate) {
            $scope.invoiceTemplate = invoiceTemplate;
            $scope.modalInstance = $modal.open({
                animation: false,
                templateUrl: 'app/views/invoicetemplate/fileupload.min.html',
                controller: 'invoiceTemplateController',
                scope: $scope,
                size: 'md',
                backdrop: false,
                resolve: {
                    invoiceTemplate: function () {
                        return $scope.invoiceTemplate;
                    }
                }
            });
        }

        $scope.cancel = function () {
            $scope.modalInstance.close();
        }
    }
})();

The javascript above that helps you create a simple angularjs file upload formdata, and don't forget to create the view upload file.

<div class="modal-primary">
    <div class="modal-content">
        <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal" ng-click="cancel()" aria-hidden="true">×</button>
            <h4 class="modal-title">Upload file</h4>
        </div>
        <div class="modal-body">
            <form name="form" role="form">
                <div class="row">
                    <div class="col-sm-12">
                        <div class="form-group">
                            <label for="templateCode">File name</label>
                            <input class="form-control" type="file" ngf-select ng-model="file" name="file" ngf-max-size="2MB" required />
                        </div>
                    </div>
                </div>
            </form>
        </div>
        <div class="modal-footer">
            <button type="button" ng-click="upload(file, invoiceTemplate)" class="btn btn-primary">Upload</button>
            <button type="button" class="btn btn-warning" data-dismiss="modal" ng-click="cancel()">Hủy</button>
        </div>
    </div>
</div>

To support multipart/form-data when using angularjs file upload formdata, you need to modify your code in the WebApiConfig.cs as shown below.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Headers;
using System.Web.Http;

namespace Invoice
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services
            config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("multipart/form-data"));

            // Web API routes
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{action}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }
}

 

Related