5

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);
};
Community
  • 1
  • 1
user2789261
  • 51
  • 1
  • 4

1 Answers1

3

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;
};
codebreach
  • 2,155
  • 17
  • 30
  • it seems to work. but how you reading form data in backend ,could you please show me the backend java code to read formdata for this example – Satish Dec 27 '13 at 06:42
  • I would recommend using Apache Commons FileUpload for this. The answer at http://stackoverflow.com/questions/2422468/how-to-upload-files-to-server-using-jsp-servlet has a very nice and detailed explanation. – codebreach Dec 28 '13 at 12:36
  • request.getInputstream() will gives the inputstream of uploaded file..but i want to take the uploaded file directly in the server side like uploadFile(HttpServletRequest req, CommonMultipartFile file) where i am sending the multipart file – Satish Dec 30 '13 at 11:47