在Asp.Net Core WebAPI中,IFormFile始终为空

18

我在使用angularjs控制器推送数据时遇到了问题。但是无论我做什么,(IFormFile file)始终为空。只有一些razor语法的示例,没有关于如何使用angular或jquery的示例。

HTML:

<form class="form-body" enctype="multipart/form-data" name="newFileForm" ng-submit="vm.addFile()"><input type="file" id="file1" name="file" multiple ng-files="getTheFiles($files)"/></form>

指令:

(function() {
'use strict';

angular
    .module('app')
    .directive('ngFiles', ['$parse', function ($parse) {

    function fn_link(scope, element, attrs) {
        var onChange = $parse(attrs.ngFiles);
        element.on('change', function (event) {
            onChange(scope, { $files: event.target.files });
        });
    };

    return {
        link: fn_link
    };
    }]);
})();

控制器

var formdata = new FormData();
    $scope.getTheFiles = function ($files) {
        angular.forEach($files, function (key, value) {
            formdata.append(key, value);
        });
    };

vm.addFile = function () {                                              
        var xhr = new XMLHttpRequest();
        xhr.open('POST', url, true);
        xhr.setRequestHeader("Content-Type", "undefined");
        xhr.send(formdata);          
    }

ASP.NET Core WebAPI:

[HttpPost]
    public async Task<IActionResult> PostProductProjectFile(IFormFile file)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        ....
        return ...;
    }

我也尝试使用formdata来完成它,因为当您使用剃刀语法进行提交时,它会被构建。类似这样:

dataService.addFile(formdata, {
            contentDisposition: "form-data; name=\"files\"; filename=\"C:\\Users\\UserName\\Desktop\\snip_20160420091420.png\"",
            contentType: "multipart/form-data",
                    headers: {
                        "Content-Disposition": "form-data; name=\"files\"; filename=\"C:\\Users\\UserName\\Desktop\\snip_20160420091420.png\"",
                        'Content-Type': "image/png"
                    },
                    fileName: "C:\\Users\\UserName\\Desktop\\snip_20160420091420.png",
                    name: "files",
                    length : 3563
            }

我在评论中写了,除了使用formData提供原始文件之外,还可以使用其他方法。但仍然没有任何反应。


如果您能分享请求正文的样子(我不关心已发布的文件内容,只关注其他部分),那将会很有帮助。您可以从浏览器的开发者工具诊断中获取它。 - Kiran
这是原始文件时的内容: lastModified:1461136463443 lastModifiedDate:Wed Apr 20 2016 09:14:23 GMT+0200 (W. Europe Daylight Time) name:"snip_20160420091420.png" size:3563 type:"image/png" webkitRelativePath:""当它是表单数据时,我无法读取它,只会显示__proto__:FormData。 - error505
4个回答

46

如果您的输入名称与方法参数名称不同,IFormFile 将无法工作。在您的情况下,输入名称为“files”,而方法参数名称为“file”。将它们设置为相同,它应该可以工作。


3
我花了好几个小时都在试图弄清楚这件事情,而这对我来说就是缺失的那个关键点。 - Quanta
谢谢你,伙计!天哪,我已经为此苦苦挣扎了好久。 - Yodacheese
我已经为此苦苦挣扎了几天。由于某种原因,它就是不起作用,在运行dotnet core 2.1 API控制器。被接受的答案有效。 - Talnaci Sergiu Vlad
惊人的杰出答案 - Rohit Kumar
我正在努力解决这个问题,但是头痛得厉害。最终我无意中找到了最小的答案,结果发现那是唯一缺失的信息。我认为这很愚蠢,因为我正在上传一个文件列表,但其中一个文件名是“file”。 - aah134

26

这是使用angularjs的方法:

vm.addFile = function () {                      
                var fileUpload = $("#file").get(0);
                var files = fileUpload.files;
                var data = new FormData();
                for (var i = 0; i < files.length ; i++) {
                    data.append(files[i].name, files[i]);
                }


                $http.post("/api/Files/", data, {
                    headers: { 'Content-Type': undefined },
                    transformRequest: angular.identity
                }).success(function (data, status, headers, config) {

                }).error(function (data, status, headers, config) {

                });
}

在 Web API 中:

[HttpPost]
public async Task<IActionResult> PostFile()
{
 //Read all files from angularjs FormData post request
 var files = Request.Form.Files;
 var strigValue = Request.Form.Keys;
 .....
}
这样也可以:
    [HttpPost]
    public async Task<IActionResult>  PostFiles(IFormCollection collection)
    {
        var f = collection.Files;                         

            foreach (var file in f)
            {
                //....
             }           
    }

谢谢,即使没有“transformRequest: angular.identity”,只需添加“'Content-Type': undefined”就足够了。 - Hasan Nafisi

2
您也可以使用Kendo上传来完成此操作,它更简单:
$("#files").kendoUpload({
        async: {
            saveUrl: dataService.upload,
            removeUrl: dataService.remove,
            autoUpload: false                                            
        },
        success: onSuccess,
        files: files
    });

1
根据@Tony Steele的回答,以下是代码示例(需要更改/注意的地方)
.NET Core 3.1 LTS
[Route("UploadAttachment")]
[HttpPost]
public async Task<IActionResult> UploadAttachment(List<IFormFile> formFiles)
{
    return Ok(await _services.UploadAttachment(formFiles));
}

AngularJS

var formFiles = new FormData();
if ($scope.files != undefined) {
    for (var i = 0; i < $scope.files.length; i++) {
       formFiles.append('formFiles', $scope.files[i]);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接