Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to upload a file using AngularJs like the traditional way

I've been tried this for days. Assuming I have a form like following:

    <form ng-submit="create()" class="form-horizontal" enctype="multipart/form-data">
      <div class="control-group">
        <label class="control-label">name : </label>
        <div class="controls">
          <input type="text" class="input-xlarge" ng-model="message.title" />
        </div>
      </div>
      <div class="control-group">
        <label class="control-label">avatar : </label>
        <div class="controls">
          <input type="file" ng-model="message.avatar" name="message[avatar]" />
        </div>
      </div>
      <div class="well">
        <input class="btn btn-large btn-primary" type="submit" value="建立資料" />
      </div>
    </form>

I am using the carrierwave gem to handle the file upload behind the scene. My controller is like this:

 $scope.create = function($scope.message){
   var deferred = $q.defer();
   $http({
       method: 'POST',
       url: '/resources/messages',
       data: $.param({message: message}),
       headers: {'Content-Type': 'multipart/form-data'}
   }).
     success(function(data, status, headers, config){
       deferred.resolve(data);
     }).
     error(function(data, status, headers, config){
       deferred.reject(status);
     });
   return deferred.promise;
  };

However it is not working. What I intend to do is create a form and upload everything like the old way, but the examples I found such as ng-upload, or like this post, or jquery file upload, they don't suit my need. Is there any example or sample code for this purpose? Thank you.

like image 273
Chuyi Huang Avatar asked Jul 13 '13 10:07

Chuyi Huang


People also ask

What is NGF select?

ngf-select is a file upload directive which defines what happens when you select the file.


1 Answers

I think "like the old way" would be to not use Ajax, but I'm guessing that's not what you mean. :)

@shaunhusain's fiddle is a good example of how to use the FormData object to handle the file upload. And using this site as a reference, you can use the transformRequest to incorporate the FormData object.

Keeping your basic $http code, modify it to add the transform object:

$scope.create = function(message){
var deferred = $q.defer();
$http({
   method: 'POST',
   url: '/resources/messages',
   data: message // your original form data,
   transformRequest: formDataObject  // this sends your data to the formDataObject provider that we are defining below.
   headers: {'Content-Type': 'multipart/form-data'}
}).
 success(function(data, status, headers, config){
   deferred.resolve(data);
 }).
 error(function(data, status, headers, config){
   deferred.reject(status);
 });
return deferred.promise;
};

Create a factory that will incorporate manipulate the form data into a sendable payload. It will iterate through your form data (including uploaded file) and return a sender-friendly object:

app.factory('formDataObject', function() {
    return function(data) {
        var fd = new FormData();
        angular.forEach(data, function(value, key) {
            fd.append(key, value);
        });
        return fd;
    };
});

I haven't tested this, but it should work out of the box.

like image 175
rGil Avatar answered Oct 28 '22 03:10

rGil