6

I'm currently uploading a file in an angular directive with...

var fd = new FormData();
fd.append("uploadedFile", scope.uploadedFile);

var xhr = new XMLHttpRequest();
xhr.upload.addEventListener("progress", uploadProgress, false);
xhr.addEventListenter("load", uploadComplete, false);
xhr.addEventListenter("error", uploadFailed, false);
xhr.addEventListenter("abort", uploadCanceled, false);
xhr.open("POST", scope.postUrl);
scope.uploadInProgress = true;
xhr.send(fd);

function uploadProgress(e){
  scope.$apply(function(){
    if(e.lengthComputable){
      scope.progress = Math.round(e.loaded * 100 / e.total);
    } else {
      scope.progress = 'unable to compute';
    }
  });
 }

 ...

Can this snippet be refactored using $http provider? i can't figure out how to keep my event listeners.

2 Answers 2

3

Short answer: soon you will be able to, but not yet exactly as you have requested.

There are a few options being discussed to build in the functionality - exposing the base xhr object, or allowing callbacks to be set for the methods.

See https://github.com/angular/angular.js/issues/1934 specifically - progress events won't work for the moment.

In the meantime, I would recommend creating an object manually and using $apply to update your scope, just as you have.

See this question for more details on how to use a service to set up at least start and stop events you can catch - but no luck on the progress.

AngularJS: need to fire event every time an ajax call is started

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

1 Comment

The feature landed in Angular 1.5.4: github.com/angular/angular.js/pull/14367/files
1

For now you can use angular-file-upload directive which is simple/lightweight and supports file drop and upload progress. It uses a shim to be loaded before the angular to be able to access XHR private object in angular and attach upload event listener to it.

<div ng-controller="MyCtrl">
  <input type="file" ng-file-select="onFileSelect($files)" multiple>
</div>

JS:

//inject angular file upload directive.
angular.module('myApp', ['angularFileUpload']);

var MyCtrl = [ '$scope', '$upload', function($scope, $upload) {
  $scope.onFileSelect = function($files) {
    for (var i = 0; i < $files.length; i++) {
      var $file = $files[i];
      $upload.upload({
        url: 'my/upload/url',
        file: $file,
        progress: function(evt){
           $scope.progress = parseInt(100.0 * evt.loaded / evt.total);
        }
      }).then(function(data, status, headers, config) {
        // file is uploaded successfully
        console.log(data);
      }); 
    }
  }
}];

Comments

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.