Base solution for your next web application
Open Closed

File upload param type when using dynamic Web API/angularjs #82


User avatar
0
matthewosullivan created

I'm using the AngularJS/EF template (which is great by the way) with the dynamic Web API layer.

I'm using the ng-file-upload directive ( [https://github.com/danialfarid/ng-file-upload]) ) and trying to send a single audio file to an ApplicationService.

Brief example <ins>Application Service</ins>

public void UploadFile(object file)

<ins>Dynamically generated Angular service</ins>

this.uploadFile = function (file, httpParams) {
	return $http(angular.extend({
		abp: true,
		url: abp.appPath + 'api/services/project/core/UploadFile',
		method: 'POST',
		data: JSON.stringify(file)
	}, httpParams));
};

<ins>Angular Controller</ins>

vm.uploadFile = function (file) {
	if (file) {
		Upload.upload({
			url: abp.appPath + 'api/services/project/core/UploadFile',
			file: file
		}).progress(function (evt) {
		    var progress = parseInt(100.0 * evt.loaded / evt.total);
			console.log('progress: ' + progress + '% ' + evt.config.file.name);
		});
	}
};

Progress is written to the console. I can see the File object in the console and it's values are set. Capturing the request in fiddler I can see: Headers: POST /api/services/project/core/UploadFile HTTP/1.1 Host: localhost:6234 Connection: keep-alive Content-Length: 9651667 Pragma: no-cache Cache-Control: no-cache Accept: application/json, text/plain, / Origin: <a class="postlink" href="http://localhost:6234">http://localhost:6234</a> User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryPcTP1YrD4qa5bhdD Referer: <a class="postlink" href="http://localhost:6234/">http://localhost:6234/</a> Accept-Encoding: gzip, deflate Accept-Language: en-US,en;q=0.8 Cookie: Abp.Localization.CultureName=en; ASP.NET_SessionId=1mtihmwrbienkqm2a1ad5vfd

Content-Disposition: form-data; name="file"; filename="yourself.wav" Content-Type: audio/wav

My question is what parameter type should Application layer methods expect when uploading a file using the dynamic Web API layer when we cannot get at the HttpRequest object? Is there any example of this?

Thanks.


6 Answer(s)
  • User Avatar
    0
    hikalkan created
    Support Team

    Have you checked the topic: #56

    You can create a custom MVC Controller or Web API controller to upload files. It's not responsibility of Application layer, so you can not do it with dynamic web api controllers.

  • User Avatar
    0
    matthewosullivan created

    I did come across that topic but I assumed that it would be best practice/cleaner to direct everything that goes to the Application layer through an Angular service, and that when using the dynamic Web API layer it would be bad to mix and match it with MVC/Web API controllers.

    I'll go with the approach you mentioned.

    Out of curiosity, would it be possible to upload a file with an Angular service that's dynamically generated?

  • User Avatar
    0
    hikalkan created
    Support Team

    Hi again,

    No, it's not bad to mix custom MVC controllers with dynamic web api layer. They are different responsibilities. But, maybe we can make it easier with ABP. Currently, I use such a code:

    Used angular module: <a class="postlink" href="https://github.com/nervgh/angular-file-upload">https://github.com/nervgh/angular-file-upload</a>

    Example controller action:

    public void ChangeProfilePicture()
    {
        if (Request.Files.Count <= 0 || Request.Files[0] == null)
        {
            throw new Exception("...");
        }
        
        var file = Request.Files[0];
    
        //change the picture..
    }
    

    Angular side controller:

    (function () {
        appModule.controller('common.views.profile.changePicture', [
            '$scope', 'appSession', '$modalInstance', 'FileUploader',
            function ($scope, appSession, $modalInstance, fileUploader) {
                var vm = this;
    
                vm.uploader = new fileUploader({
                    url: abp.appPath + 'Profile/ChangeProfilePicture',
                    queueLimit: 1,
                    filters: [{
                        name: 'imageFilter',
                        fn: function (item, options) {
                            //File type check
                            var type = '|' + item.type.slice(item.type.lastIndexOf('/') + 1) + '|';
                            if ('|jpg|jpeg|'.indexOf(type) === -1) {
                                abp.message.warn(app.localize('ProfilePicture_Warn_FileType'));
                                return false;
                            }
    
                            //File size check
                            if (item.size > 30720) //30KB
                            {
                                abp.message.warn(app.localize('ProfilePicture_Warn_SizeLimit'));
                                return false;
                            }
    
                            return true;
                        }
                    }]
                });
    
                vm.save = function () {
                    vm.uploader.uploadAll();
                };
    
                vm.cancel = function () {
                    $modalInstance.dismiss();
                };
    
                vm.uploader.onSuccessItem = function (fileItem, response, status, headers) {
                    $modalInstance.close();
                };
            }
        ]);
    })();
    

    Angular view related part

    <input type="file" nv-file-select uploader="vm.uploader" />
    
  • User Avatar
    0
    matthewosullivan created

    Thanks for clearing that up and the example, much appreciated.

  • User Avatar
    0
    ojukwu24 created

    <cite>hikalkan: </cite> Hi again,

    No, it's not bad to mix custom MVC controllers with dynamic web api layer. They are different responsibilities. But, maybe we can make it easier with ABP. Currently, I use such a code:

    Used angular module: <a class="postlink" href="https://github.com/nervgh/angular-file-upload">https://github.com/nervgh/angular-file-upload</a>

    Example controller action:

    public void ChangeProfilePicture()
    {
       if (Request.Files.Count <= 0 || Request.Files[0] == null)
       {
           throw new Exception("...");
       }
       
       var file = Request.Files[0];
    
       //change the picture..
    }
    

    Angular side controller:

    (function () {
       appModule.controller('common.views.profile.changePicture', [
           '$scope', 'appSession', '$modalInstance', 'FileUploader',
           function ($scope, appSession, $modalInstance, fileUploader) {
               var vm = this;
    
               vm.uploader = new fileUploader({
                   url: abp.appPath + 'Profile/ChangeProfilePicture',
                   queueLimit: 1,
                   filters: [{
                       name: 'imageFilter',
                       fn: function (item, options) {
                           //File type check
                           var type = '|' + item.type.slice(item.type.lastIndexOf('/') + 1) + '|';
                           if ('|jpg|jpeg|'.indexOf(type) === -1) {
                               abp.message.warn(app.localize('ProfilePicture_Warn_FileType'));
                               return false;
                           }
    
                           //File size check
                           if (item.size > 30720) //30KB
                           {
                               abp.message.warn(app.localize('ProfilePicture_Warn_SizeLimit'));
                               return false;
                           }
    
                           return true;
                       }
                   }]
               });
    
               vm.save = function () {
                   vm.uploader.uploadAll();
               };
    
               vm.cancel = function () {
                   $modalInstance.dismiss();
               };
    
               vm.uploader.onSuccessItem = function (fileItem, response, status, headers) {
                   $modalInstance.close();
               };
           }
       ]);
    })();
    

    Angular view related part

    <input type="file" nv-file-select uploader="vm.uploader" />
    

    I have tried using this same method to upload a video, but it doesn't get to the Controller.

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    Can you share some more details ? Do you have any client side or server side errors ?

    You can check Logs.txt for server side errors. It should be under your web project.

    Thanks.