IFormFile is always empty in Asp.Net Core WebAPI
Asked Answered
J

5

18

I have a problem here when I am trying to push data with angularjs controller. But what ever I do (IFormFile file) is always empty. There are only some examples with razor syntax but no examples how to do it with angular or 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>

Directive:

(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
    };
    }]);
})();

Controller

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 ...;
    }

I have also tried to do it with formdata, as it is constructed when you post it with razor syntax. Something like this:

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
            }

Also instead of formData to provide raw file as I wrote in comment. But still nothing happens

Joyajoyan answered 1/7, 2016 at 11:23 Comment(2)
it would help if you could share how your request body looks like (i am not interested in the posted file content but everything else). You can grab it from a browser's developer tool diagnostics.Natale
This is when it is rawfile 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:"" And when it is form data than I cant read it, it is just __proto__:FormDataJoyajoyan
J
26

This is how to do it with 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) {

                });
}

And in 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;
 .....
}

Or like this:

    [HttpPost]
    public async Task<IActionResult>  PostFiles(IFormCollection collection)
    {
        var f = collection.Files;                         

            foreach (var file in f)
            {
                //....
             }           
    }
Joyajoyan answered 4/7, 2016 at 14:15 Comment(1)
Thanks, Its also work without " transformRequest: angular.identity", just add " 'Content-Type': undefined " is enough.Fissionable
W
47

IFormFile will only work if you input name is the same as your method parameter name. In your case the input name is 'files' and the method parameter name is 'file'. Make them the same and it should work.

Wiggly answered 24/1, 2017 at 0:10 Comment(5)
I've been trying to figure this out for hours, and this was the missing piece, for me.Annotation
Thank you dude! Holly crap been struggling on that for ages.Conglomeration
I've struggled for a few days with this. For some reason it just does not work, running dotnet core 2.1 API controller. The accepted answer works.Cassicassia
amazing brilliant answerSelfoperating
I am having a very bad headache trying to figure this out, finally I see the smallest answer by mistake, which turned out to be the only missing info. I think this is stupid because I am uploading a list of files, but one file name is file.Perzan
J
26

This is how to do it with 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) {

                });
}

And in 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;
 .....
}

Or like this:

    [HttpPost]
    public async Task<IActionResult>  PostFiles(IFormCollection collection)
    {
        var f = collection.Files;                         

            foreach (var file in f)
            {
                //....
             }           
    }
Joyajoyan answered 4/7, 2016 at 14:15 Comment(1)
Thanks, Its also work without " transformRequest: angular.identity", just add " 'Content-Type': undefined " is enough.Fissionable
L
2

You can do it also with kendo upload much simpler:

$("#files").kendoUpload({
        async: {
            saveUrl: dataService.upload,
            removeUrl: dataService.remove,
            autoUpload: false                                            
        },
        success: onSuccess,
        files: files
    });
Lylelyles answered 8/11, 2016 at 8:46 Comment(0)
S
1

From the answer of @Tony Steele. Here is the code sample (Where to change/take care of)

.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]);
    }
}
Suffruticose answered 9/7, 2021 at 2:31 Comment(0)
C
0
   if multiple file upload:

    
const formData = new FormData();
    this.fileList.forEach((file: any) => {
     formData.append('pictures', file['originFileObj']);
    });
    
    public async Task<IActionResult> Post(List<FromForm> pictures)
    {
      return Ok();
    }
    

 if single file upload:

    
    const formData = new FormData();
        this.fileList.forEach((file: any) => {
         formData.append(file['name'], file['originFileObj']);
        });
Castra answered 22/2 at 2:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.