如何在MVC中使用AngularJS上传文件

时间:2021-08-30 12:12:26

As I am new to AngularJS, I Don't know how to upload file in MVC using AngularJS. I am trying to upload some files without any specific type or extension, but failed.

由于我是AngularJS的新手,我不知道如何使用AngularJS在MVC中上传文件。我试图上传一些没有任何特定类型或扩展名的文件,但失败了。

I created a javascript file which have-

我创建了一个javascript文件,它有 -

Here is serviceJS-

这是serviceJS-

    var app = angular.module("app", []);        
    app.service('FileUploadService', ['$http', function ($http) {      
            this.uploadFileToUrl = function (file,  uploadUrl) {    
            var fd = new FormData();   
            fd.append('file', file);   
            $http.post(uploadUrl, fd, {   
                transformRequest: angular.identity,   
                headers: { 'Content-Type': undefined }   
            })   
            .success(function () {   
            })    
            .error(function () {    
            });     
        }   
    }]);

This is controller part-

这是控制器部分 -

    app.controller('FileUploadController', ['$scope', 'FileUploadService', function($scope, FileUploadService) { 
            $scope.uploadFile = function () {
            var file = $scope.myFile;
            console.log('file is ');
            console.dir(file);
            var uploadUrl = "/Home/FileUploadFromAngular";
            FileUploadService.uploadFileToUrl(file, uploadUrl);
        };
    }]);

And, In view page,

并且,在视图页面中,

 <script src="~/Scripts/angular.min.js"></script>
<script src="~/Scripts/AngScript/FileUpload.js"></script>
<script src="~/Scripts/angular-ui/ui-bootstrap.min.js"></script>
    <div ng-controller="FileUploadController">
        <input type="file" ng-model="myFile" />
        <button ng-click="uploadFile()">Upload</button>
    </div>

It is taking myFile as undefined in controller. I am unable to debug this.
Thanks in advance.

它将myFile作为未定义的控制器。我无法调试这个。提前致谢。

3 个解决方案

#1


4  

You cannot bind the an <input type="file"> to an $scope variable. You will need to create a directive which captures the onchange event of the file input tag. for example <input type="file" name="myFile" file-upload/> and the directive looks like this:

您不能将绑定到$ scope变量。您需要创建一个捕获文件输入标记的onchange事件的指令。例如,指令如下所示:

angular.module("app.directives", []).directive('fileUpload', function () {
return {
    scope: true,
    link: function (scope, el, attrs) {
        el.bind('change', function (event) {
            var files = event.target.files;
            //iterate files since 'multiple' may be specified on the element
            if(files.length == 0){
                scope.$emit("fileSelected", { file: null, field: event.target.name });
            } else{
                for (var i = 0;i<files.length;i++) {
                    //emit event upward
                    scope.$emit("fileSelected", { file: files[i], field: event.target.name });
                }
            }
        });
    }
};
});

After that, you can catch the broadcast in your controller like this:

之后,您可以在控制器中捕获广播,如下所示:

$scope.$on("fileSelected", function (event, args) {
    $scope.$apply(function () {
        switch (args.field) {
            case "myFile":
                $scope.myFile = args.file;
                break;
            default:
                break;
        }
    });
});

Your Service method can be comething like this:

您的服务方法可以是这样的:

this.uploadFileToUrl = function (file,  uploadUrl) { 
    return $http({
        method: 'POST',
        url: uploadUrl,
        headers: { 'Content-Type': undefined },
        transformRequest: function() {
            var formData = new FormData();
            if(file){
               formData.append("myFile", file); 
            }
            return formData;
        }
    })
}

#2


0  

Try this. Controller

尝试这个。调节器

/**** FILE UPLOAD *****/

/**** 上传文件 *****/

   $scope.upload = [];
    $scope.fileUploadObj = {
        "ID": $rootScope.filesReturn.id
    }

    $scope.onMultiFileSelect = function ($files) {
        //$files: an array of files selected, each file has name, size, and type.
    $scope.errArr = [];
    for (var i = 0; i < $files.length; i++) {
        var $file = $files[i];
        if ($file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' || $file.type === 'application/vnd.ms-excel') {
            (function (index) {
                $scope.upload[index] = $upload.upload({
                    url: host + 'api/Return/ReturnUpload',
                    method: "POST",
                    data: { fileUploadObj: $scope.fileUploadObj },
                    file: $file
                }).progress(function (evt) {
                    // get upload percentage Can hook to some Load view thing
                    //console.log('percent: ' + parseInt(100.0 * evt.loaded / evt.total));
                }).success(function (data, status, headers, config) {
                    // file is uploaded successfully
                    $scope.chkErr();
                }).error(function (data, status, headers, config) {
                    // file failed to upload
                    $scope.setErr(data.returnDataErr);
                    $scope.chkErr();
                });
            })(i);
        }
        else
        {
            $scope.setErr($file.name + " is not an .xls .xlsx");
            $scope.chkErr();
            (i);
        }
    }//END FOR
    $scope.abortUpload = function (index) {
        $scope.upload[index].abort();
    }
}
//check if there is errormsg in array.
$scope.chkErr = function () {
    if ($scope.errArr.length > 0) {
        //IS ERROR
        $scope.errorUpload = true;
        $scope.$apply();
        //$scope.errorMessage = data.returnDataErr;
    }
    else {
        //IS SUCCESS
        $scope.noFiles = false;
        $scope.errorUpload = false;
        $scope.getFiles();
    }
}

View

视图

                            <div class="col-xs-12 col-sm-6 col-md-6 col-lg-6">
                                <input style="float:left" type="file" ng-file-select="onMultiFileSelect($files)" multiple>
                                <div style ="float:left">
                                    <a ng-show="!noFiles" class=" btn btn-default btn-xs" ng-click="confirmClick() && deleteItem()" confirm-click data-localize="DELETE">
                                        Delete All
                                    </a>
                                </div>
                            </div>

API or MVC controller

API或MVC控制器

  [Route("ReturnUpload")]
    [HttpPost]
    public async Task<HttpResponseMessage> ReturnUpload()
    {
        if (!Request.Content.IsMimeMultipartContent())
        {
            this.Request.CreateResponse(HttpStatusCode.UnsupportedMediaType);
        }

        try
        {
            var provider = GetMultipartProvider();
            var result = await Request.Content.ReadAsMultipartAsync(provider);

            //JSON data from upload ( returns id )
            var returns = GetFormData<UploadReturnBindingModel>(result) as UploadReturnBindingModel;

            //Get original FileName from result
            var originalFileName = GetDeserializedFileName(result.FileData.First());

            //Get data from UplaodedFile info.  paths created time etc.
            var uploadedFileInfo = new FileInfo(result.FileData.First().LocalFileName);

            var ret = db.ReturnRecords.Single(a => a.id == returns.ID);
            var tenantId = db.Users.Find(User.Identity.GetUserId()).Tenant.id;
            var entityId = ret.entityId;
            if (ret.status == ReturnStatus.Converting.ToString())
            {
                // If you want to send something to the .error callback, 
                var returnDataErr = "Convertion in Progress, try again later";
                return this.Request.CreateResponse(HttpStatusCode.BadRequest, new { returnDataErr });
            }

            var ToDir = uploadedFileInfo.DirectoryName + "\\" + tenantId + "\\" + entityId + "\\" + returns.ID + "\\Upload\\";
            if (!Directory.Exists(ToDir))
            {
                Directory.CreateDirectory(ToDir);
            }
            else if (System.IO.File.Exists(ToDir + originalFileName))
            {
                var toDelete = db.FileRecords.Single(a => a.path + a.name == ToDir + originalFileName && a.returnId == returns.ID);
                db.FileRecords.Remove(toDelete);
                System.IO.File.Delete(ToDir + originalFileName);
            }
            System.IO.File.Move(uploadedFileInfo.FullName, ToDir + originalFileName);

            var file = new Portal.Models.File();
            file.userName = db.Users.Find(User.Identity.GetUserId()).UserName;
            file.name = originalFileName;
            file.path = ToDir;
            file.returnId = returns.ID;
            file.timeStamp = DateTime.Now;
            //var createdTime = uploadedFileInfo.CreationTime;
            //var currentUser =  User.Identity.GetUserId();
            db.FileRecords.Add(file);


            // Update the ret status that files has been uploaded.
            ret.status = ReturnStatus.DocumentsUploaded.ToString();

            db.SaveChanges();


        }
        catch(Exception ex)
        {
            // If you want to send something to the .error callback, use the HttpStatusCode.BadRequest instead
            log.Error(ex);
            var returnDataErr = "Failed creating file";
            return this.Request.CreateResponse(HttpStatusCode.BadRequest, new { returnDataErr });
        }
        // Through the request response you can return an object to the Angular controller
        // You will be able to access this in the .success callback through its data attribute
        var returnDataOk = "OK";
        return this.Request.CreateResponse(HttpStatusCode.OK, new { returnDataOk });
    }

#3


0  

<input class="input-sm" type="file" ng-model="Registration_CTRL.IDProdf" onchange="angular.element(this).scope().FN_UPLOAD_FILE(event)" multiple />

$scope.FN_UPLOAD_FILE = function (evt) {
        var _file = new File([""], evt.target.file);
        var a = evt.target.files;
        var _formData = new FormData();
        _formData.append("IDPROOF", evt.target.files[0]);
        _formData.append("EMPID", $scope.Registration_CTRL.ID);
        $http({
            method: 'POST',
            url: '@Url.Action("Upload_Employee_IDProof", "Registration")',
            headers: { 'Content-Type': undefined },
            data: _formData
        }).then(function (data) {
            $scope.Registration_CTRL.IDProdf = data.data.aaData;
        });
    }

[HttpPost]
public JsonResult Upload_Employee_IDProof()
{
    string _fileName = "";
    try
    {
        if (Request.Files.Count > 0)
        {
            var _empid = int.Parse(Request.Form["EMPID"]);
            var _file = Request.Files[0];
            var _fName = Request.Files["IDPROOF"].FileName;
            var _dotIndex = _fName.LastIndexOf('.');
            var _ext = _fName.Substring(_dotIndex);
            var _configpath = RequestHelpers.RequestHelpers.GetConfigurationValue("IDProofPath");
            _fileName = _empid + "_IDPROOF" + _ext;
            var _dirPath = Server.MapPath(_configpath);
            var _filePath = Server.MapPath(_configpath) + _fileName;
            if (System.IO.Directory.Exists(_dirPath))
            {
                if (System.IO.File.Exists(_filePath))
                {
                    System.IO.File.Delete(_filePath);
                }
                _file.SaveAs(_filePath);
            }
            else
            {
                System.IO.Directory.CreateDirectory(_dirPath);
                _file.SaveAs(_filePath);
            }
        }
    }
    catch (Exception ex)
    {
        return Json(new { aaData = ex.Message }, JsonRequestBehavior.AllowGet);
    }
    return Json(new { aaData = _fileName }, JsonRequestBehavior.AllowGet);
}

#1


4  

You cannot bind the an <input type="file"> to an $scope variable. You will need to create a directive which captures the onchange event of the file input tag. for example <input type="file" name="myFile" file-upload/> and the directive looks like this:

您不能将绑定到$ scope变量。您需要创建一个捕获文件输入标记的onchange事件的指令。例如,指令如下所示:

angular.module("app.directives", []).directive('fileUpload', function () {
return {
    scope: true,
    link: function (scope, el, attrs) {
        el.bind('change', function (event) {
            var files = event.target.files;
            //iterate files since 'multiple' may be specified on the element
            if(files.length == 0){
                scope.$emit("fileSelected", { file: null, field: event.target.name });
            } else{
                for (var i = 0;i<files.length;i++) {
                    //emit event upward
                    scope.$emit("fileSelected", { file: files[i], field: event.target.name });
                }
            }
        });
    }
};
});

After that, you can catch the broadcast in your controller like this:

之后,您可以在控制器中捕获广播,如下所示:

$scope.$on("fileSelected", function (event, args) {
    $scope.$apply(function () {
        switch (args.field) {
            case "myFile":
                $scope.myFile = args.file;
                break;
            default:
                break;
        }
    });
});

Your Service method can be comething like this:

您的服务方法可以是这样的:

this.uploadFileToUrl = function (file,  uploadUrl) { 
    return $http({
        method: 'POST',
        url: uploadUrl,
        headers: { 'Content-Type': undefined },
        transformRequest: function() {
            var formData = new FormData();
            if(file){
               formData.append("myFile", file); 
            }
            return formData;
        }
    })
}

#2


0  

Try this. Controller

尝试这个。调节器

/**** FILE UPLOAD *****/

/**** 上传文件 *****/

   $scope.upload = [];
    $scope.fileUploadObj = {
        "ID": $rootScope.filesReturn.id
    }

    $scope.onMultiFileSelect = function ($files) {
        //$files: an array of files selected, each file has name, size, and type.
    $scope.errArr = [];
    for (var i = 0; i < $files.length; i++) {
        var $file = $files[i];
        if ($file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' || $file.type === 'application/vnd.ms-excel') {
            (function (index) {
                $scope.upload[index] = $upload.upload({
                    url: host + 'api/Return/ReturnUpload',
                    method: "POST",
                    data: { fileUploadObj: $scope.fileUploadObj },
                    file: $file
                }).progress(function (evt) {
                    // get upload percentage Can hook to some Load view thing
                    //console.log('percent: ' + parseInt(100.0 * evt.loaded / evt.total));
                }).success(function (data, status, headers, config) {
                    // file is uploaded successfully
                    $scope.chkErr();
                }).error(function (data, status, headers, config) {
                    // file failed to upload
                    $scope.setErr(data.returnDataErr);
                    $scope.chkErr();
                });
            })(i);
        }
        else
        {
            $scope.setErr($file.name + " is not an .xls .xlsx");
            $scope.chkErr();
            (i);
        }
    }//END FOR
    $scope.abortUpload = function (index) {
        $scope.upload[index].abort();
    }
}
//check if there is errormsg in array.
$scope.chkErr = function () {
    if ($scope.errArr.length > 0) {
        //IS ERROR
        $scope.errorUpload = true;
        $scope.$apply();
        //$scope.errorMessage = data.returnDataErr;
    }
    else {
        //IS SUCCESS
        $scope.noFiles = false;
        $scope.errorUpload = false;
        $scope.getFiles();
    }
}

View

视图

                            <div class="col-xs-12 col-sm-6 col-md-6 col-lg-6">
                                <input style="float:left" type="file" ng-file-select="onMultiFileSelect($files)" multiple>
                                <div style ="float:left">
                                    <a ng-show="!noFiles" class=" btn btn-default btn-xs" ng-click="confirmClick() && deleteItem()" confirm-click data-localize="DELETE">
                                        Delete All
                                    </a>
                                </div>
                            </div>

API or MVC controller

API或MVC控制器

  [Route("ReturnUpload")]
    [HttpPost]
    public async Task<HttpResponseMessage> ReturnUpload()
    {
        if (!Request.Content.IsMimeMultipartContent())
        {
            this.Request.CreateResponse(HttpStatusCode.UnsupportedMediaType);
        }

        try
        {
            var provider = GetMultipartProvider();
            var result = await Request.Content.ReadAsMultipartAsync(provider);

            //JSON data from upload ( returns id )
            var returns = GetFormData<UploadReturnBindingModel>(result) as UploadReturnBindingModel;

            //Get original FileName from result
            var originalFileName = GetDeserializedFileName(result.FileData.First());

            //Get data from UplaodedFile info.  paths created time etc.
            var uploadedFileInfo = new FileInfo(result.FileData.First().LocalFileName);

            var ret = db.ReturnRecords.Single(a => a.id == returns.ID);
            var tenantId = db.Users.Find(User.Identity.GetUserId()).Tenant.id;
            var entityId = ret.entityId;
            if (ret.status == ReturnStatus.Converting.ToString())
            {
                // If you want to send something to the .error callback, 
                var returnDataErr = "Convertion in Progress, try again later";
                return this.Request.CreateResponse(HttpStatusCode.BadRequest, new { returnDataErr });
            }

            var ToDir = uploadedFileInfo.DirectoryName + "\\" + tenantId + "\\" + entityId + "\\" + returns.ID + "\\Upload\\";
            if (!Directory.Exists(ToDir))
            {
                Directory.CreateDirectory(ToDir);
            }
            else if (System.IO.File.Exists(ToDir + originalFileName))
            {
                var toDelete = db.FileRecords.Single(a => a.path + a.name == ToDir + originalFileName && a.returnId == returns.ID);
                db.FileRecords.Remove(toDelete);
                System.IO.File.Delete(ToDir + originalFileName);
            }
            System.IO.File.Move(uploadedFileInfo.FullName, ToDir + originalFileName);

            var file = new Portal.Models.File();
            file.userName = db.Users.Find(User.Identity.GetUserId()).UserName;
            file.name = originalFileName;
            file.path = ToDir;
            file.returnId = returns.ID;
            file.timeStamp = DateTime.Now;
            //var createdTime = uploadedFileInfo.CreationTime;
            //var currentUser =  User.Identity.GetUserId();
            db.FileRecords.Add(file);


            // Update the ret status that files has been uploaded.
            ret.status = ReturnStatus.DocumentsUploaded.ToString();

            db.SaveChanges();


        }
        catch(Exception ex)
        {
            // If you want to send something to the .error callback, use the HttpStatusCode.BadRequest instead
            log.Error(ex);
            var returnDataErr = "Failed creating file";
            return this.Request.CreateResponse(HttpStatusCode.BadRequest, new { returnDataErr });
        }
        // Through the request response you can return an object to the Angular controller
        // You will be able to access this in the .success callback through its data attribute
        var returnDataOk = "OK";
        return this.Request.CreateResponse(HttpStatusCode.OK, new { returnDataOk });
    }

#3


0  

<input class="input-sm" type="file" ng-model="Registration_CTRL.IDProdf" onchange="angular.element(this).scope().FN_UPLOAD_FILE(event)" multiple />

$scope.FN_UPLOAD_FILE = function (evt) {
        var _file = new File([""], evt.target.file);
        var a = evt.target.files;
        var _formData = new FormData();
        _formData.append("IDPROOF", evt.target.files[0]);
        _formData.append("EMPID", $scope.Registration_CTRL.ID);
        $http({
            method: 'POST',
            url: '@Url.Action("Upload_Employee_IDProof", "Registration")',
            headers: { 'Content-Type': undefined },
            data: _formData
        }).then(function (data) {
            $scope.Registration_CTRL.IDProdf = data.data.aaData;
        });
    }

[HttpPost]
public JsonResult Upload_Employee_IDProof()
{
    string _fileName = "";
    try
    {
        if (Request.Files.Count > 0)
        {
            var _empid = int.Parse(Request.Form["EMPID"]);
            var _file = Request.Files[0];
            var _fName = Request.Files["IDPROOF"].FileName;
            var _dotIndex = _fName.LastIndexOf('.');
            var _ext = _fName.Substring(_dotIndex);
            var _configpath = RequestHelpers.RequestHelpers.GetConfigurationValue("IDProofPath");
            _fileName = _empid + "_IDPROOF" + _ext;
            var _dirPath = Server.MapPath(_configpath);
            var _filePath = Server.MapPath(_configpath) + _fileName;
            if (System.IO.Directory.Exists(_dirPath))
            {
                if (System.IO.File.Exists(_filePath))
                {
                    System.IO.File.Delete(_filePath);
                }
                _file.SaveAs(_filePath);
            }
            else
            {
                System.IO.Directory.CreateDirectory(_dirPath);
                _file.SaveAs(_filePath);
            }
        }
    }
    catch (Exception ex)
    {
        return Json(new { aaData = ex.Message }, JsonRequestBehavior.AllowGet);
    }
    return Json(new { aaData = _fileName }, JsonRequestBehavior.AllowGet);
}