0

I can upload a single file but not using multiple. How can i do it?

this is what i tried so far:

var myApp = angular.module('myApp', []);

myApp.directive('fileModel', ['$parse', function ($parse) {
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
            var model = $parse(attrs.fileModel);
            var modelSetter = model.assign;

            element.bind('change', function(){
                scope.$apply(function(){
                    modelSetter(scope, element[0].files[0]);
                    console.log(element[0].files[0]);
                });
            });
        }
    };
}]);

myApp.service('fileUpload', ['$http', function ($http) {
    this.uploadFileToUrl = function(file, uploadUrl, callback){
        var fd = new FormData();
        var files = file;
        fd.append('file', file);    

        $http.post(uploadUrl, fd, {
            transformRequest: angular.identity,
            headers: {'Content-Type': undefined}
        })
        .success(callback)
        .error(callback);
    }
}]);

myApp.controller('myCtrl', ['$scope', 'fileUpload', function($scope, fileUpload){

    $scope.uploadFile = function(){
        var file = $scope.myFile;
        console.log('file is ' + JSON.stringify(file.name));

        var uploadUrl = "http://httpbin.org/post";
        fileUpload.uploadFileToUrl(file, uploadUrl,function(data, status, headers, config){
            if(status == 200)console.log('Success!');
            else console.log('Error!');
        });
    };

}]);

the html:

<div ng-controller = "myCtrl">
    <form>
        <input type="file" multiple file-model="myFile"/>
        <button ng-click="uploadFile()">upload me</button>
    </form>

    {{myFile.name}}
</div>

here the jsfiddle: http://jsfiddle.net/ejx68/7/

6
  • why did you not use github.com/Wildhoney/ngDroplet or github.com/flowjs/ng-flow? Commented May 25, 2015 at 13:03
  • Nice suggestion but i need to use this way..can you help me please? Commented May 25, 2015 at 13:05
  • I was able to select two files, I can't be sure if they upload correctly. It only shows one file name because myFile.name is the last of multiple files. Commented May 25, 2015 at 13:10
  • @cabey77 can you show me how could i do it? Commented May 25, 2015 at 13:11
  • @End.Game Did you try to pass an array of files? Commented May 25, 2015 at 13:12

2 Answers 2

2

Your code has two issues that are against your intentions.

I fixed your Fiddle, but will highlight what's wrong.

  1. With that for loop in the directive, you are dropping all but the last selected files. You shouldn't use the for loops at all, they make no sense there! Just pass in the array of files.

    element.bind('change', function () {
        scope.$apply(function () {
            modelSetter(scope, element[0].files);
        });
    });
    
  2. The actual upload function only handles single files, when it should expect an array and upload all items.

    $scope.uploadFile = function () {
        var files = $scope.myFile,
            uploadUrl = "http://httpbin.org/post";
    
        function callback(data, status, headers, config) {
            if (status == 200) console.log('Success!');
            else console.log('Error!');
        }
    
        for (var i = 0; i < files.length; i++) {
            var file = files[i];
            console.log('file is ' + JSON.stringify(file.name));
            fileUpload.uploadFileToUrl(file, uploadUrl, callback);
        }
    };
    

    Or, if you want to upload all files in a single request, you can modify uploadFileToUrl to add every file to FormData.

Sign up to request clarification or add additional context in comments.

2 Comments

well, it's not really wrong, but in this way it make the request twice. One for each file. I need to do the request only one time with all files.
and the service fileUpload isn't to modify?
0

This will handle all the files and set them into the model.

myApp.directive('fileModel', ['$parse', function ($parse) {
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
            var model = $parse(attrs.fileModel);
            var modelSetter = model.assign;

            element.bind('change', function(){
                scope.$apply(function(){
                    for(int i=0; i<element[0].files.length; i++)
                    {
                       modelSetter(scope, element[0].files[i]);
                    }
                    for(int i=0; i<element[0].files.length; i++)
                    {
                       console.log(element[0].files[i]);
                    }
                });
            });
        }
    };
}]);
//If api does not take an array of files
myApp.controller('myCtrl', ['$scope', 'fileUpload', function($scope, fileUpload){

    $scope.uploadFile = function(){
        var file = $scope.myFile;
        console.log('file is ' + JSON.stringify(file.name));

        var uploadUrl = "http://httpbin.org/post";
        for(int i=0; i<file.length; i++)
       {
        fileUpload.uploadFileToUrl(file[i], uploadUrl,function(data, status, headers, config){
            if(status == 200)console.log('Success!');
            else console.log('Error!');
        });
       }
    };

}]);

4 Comments

and nothing else? when i have to append the formData?
Depends if that api handles an array of files. If not you would have to loop through the var file and call fileUpload.uploadToUrl() each time
please can you try using the jsfiddle? I tried in your way but not working. The request doesn't start anymore.
My solution is the same as vzsg, except his is actually written better. You have to look at the api to see what it takes as post data.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.