user2789261
user2789261

Reputation: 51

Example of progress on file upload in AngularJS $http POST

I am trying to get a 'progress' event from AngularJS $http POST request for file upload.

After looking at $http upload file progress in AngularJS, I came across one recent angular.js git commit, that suppose to resolve the issue Add XHR progress event handling to $http and $httpBackend.

Did anyone achieve this working? And if so, can kindly show the example?

PS. I'd prefer to stay with $http rather than create my own XMLHttpRequest. The reason is that my backend expects to get json object combined with multipart file data. And the attempt to make through XMLHttpRequest is failing with error message that backend doesn't see the json object part of request "Required String parameter 'objData' is not present. The request sent by the client was syntactically incorrect." While in the POST message I see "Content-Disposition: form-data; name="objData"" in Firebug.

   $scope.uploadFile = function() {
    var url = buildUrl('/upload');
    var data = {objData: $scope.data, fileData: $scope.file};
    var formData = new FormData();

    formData.append("objData", angular.toJson(data.objData));
    formData.append("fileData", data.fileData);

    var xhr = new window.XMLHttpRequest();

    xhr.upload.addEventListener("progress", uploadProgress, false);

    xhr.open("POST", url);
    xhr.setRequestHeader("Content-Type","application/json;charset=utf-8");
    xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
    xhr.send(formData);
};

Upvotes: 5

Views: 7379

Answers (1)

codebreach
codebreach

Reputation: 2220

At time of writing $http doesn't support the notify method of the new 1.2 $q. So you have to use jquery xhr. Its rather simple once set up:

Notice that we return a promise so your consumer of uploadFile would do uploadFile(..).then(success, fail, progress)

$scope.uploadFile = function() {
  var deferred = $q.defer();
  var getProgressListener = function(deferred) {
    return function(event) {
      //do some magic
      deferred.notify(magic);
    };
  };
  var formData = new FormData();

  formData.append("objData", angular.toJson(data.objData));
  formData.append("fileData", data.fileData);

  $.ajax({
    type: 'POST',
    url: buildUrl('/upload'),
    data: formData,
    cache: false,
    // Force this to be read from FormData
    contentType: false,
    processData: false,
    success: function(response, textStatus, jqXHR) {
      deferred.resolve(response);
    },
    error: function(jqXHR, textStatus, errorThrown) {
      deferred.reject(errorThrown);
    },
    xhr: function() {
      var myXhr = $.ajaxSettings.xhr();
      if (myXhr.upload) {
         myXhr.upload.addEventListener(
            'progress', getProgressListener(deferred), false);
      } else {
        $log.log('Upload progress is not supported.');
      }
      return myXhr;
    }
  });
  return deferred.promise;
};

Upvotes: 3

Related Questions