file uploader integration for angularjs

File UploadAngularjs

File Upload Problem Overview


Does there exist a good file uploader with good integration (a directive) for AngularJS?

I am looking for something that is easy to style and supports HTML5 drag and drop etc.

Someone will probably say that its easy to use an existing uploader and integrate it into AngularJS - to that I'll say: if its easy then someone should have done it already.

File Upload Solutions


Solution 1 - File Upload

I actually have rolled my own uploader once... but only because I didn't like any of the already made JQuery ones. Unfortunately that's proprietary and I can't post it on the internet... but... I can show you how to use just about any JQuery plugin from Angular:

> Someone will probably say that its easy to use an existing uploader and integrate it into AngularJS - to that i'll say: if its easy then someone should have done it already.

Let's presume I have a jQuery plugin that works by selecting a div and calling pluginUploadCall() on it...

app.directive('myJqueryPluginUploader', function() {
   return {
      restrict: 'A',
      link: function(scope, elem, attr, ctrl) {
          // elem is a jQuery lite object
          // or a jQuery object if jQuery is present.
          // so call whatever plugins you have.
          elem.pluginUploadCall();
      }
   };
});

And here's how it would be used.

<div my-jquery-plugin-uploader></div>

Angular actually integrates really well with jQuery so any plugins that work in jQuery should work pretty easily in Angular. The only trickiness comes in when you want to keep Dependency Injection alive so you can keep your Angular App testable. JQuery isn't very good at DI, so you may have to jump through some hoops.

If you wanted to roll your own, I can tell you I did something like this:

app.directive('customUploader', function(){
    return {
       restrict: 'E',
       scope: {},
       template: '<div class="custom-uploader-container">Drop Files Here<input type="file" class="custom-uploader-input"/><button ng-click="upload()" ng-disabled="notReady">Upload</button></div>',
       controller: function($scope, $customUploaderService) {
          $scope.notReady = true;
          $scope.upload = function() {
             //scope.files is set in the linking function below.
             $customUploaderService.beginUpload($scope.files);
          };
          $customUploaderService.onUploadProgress = function(progress) {
             //do something here.
          };
          $customUploaderService.onComplete = function(result) {
             // do something here.
          };
       },
       link: function(scope, elem, attr, ctrl) {
          fileInput = elem.find('input[type="file"]');
          fileInput.bind('change', function(e) {               
               scope.notReady = e.target.files.length > 0;
               scope.files = [];
               for(var i = 0; i < e.target.files.length; i++) {
                   //set files in the scope
                   var file = e.target.files[i];
                   scope.files.push({ name: file.name, type: file.type, size: file.size });
               }
          });
       }
});

Where $customUploaderService would be a custom service you create with Module.factory() that uses $http to post the files and check the progress on the server.

I know that's vague, and I'm sorry that's all I can provide, but I hope that helps.

EDIT: The drag and drop file upload is a bit of a trick of CSS, BTW... for Chrome and FF, what you do is put the in a containing div... then do something like this:

<div class="uploadContainer">Drop Files Here<input type="file"/></div>

div.uploadContainer {
   position: relative;
   width: 600px;
   height: 100px;
}

div.uploadContainer input[type=file] {
   visibility: hidden;
   position: absolute;
   top: 0;
   bottom: 0;
   left: 0;
   right: 0;
}

... now anything you drop on that div will really be dropped on the file upload, and you can make the div look like whatever you want.

Solution 2 - File Upload

You can give AngularJS.ngUpload a try.

It's an HTML5-free solution that uses an invisible iFrame for file upload. Since it does not rely on HTML5, it works across browser!

Sample code:

<form action='/server/upload/handler' ng-upload="callbackFunction">
   <!-- other form inputs goes here -->
   <input type="file" name="anyEasyName" />
   <input type="submit" class="upload-submit" value="Submit" />
</form>
<div>{{uploadReport}}</div>

Any html element that supports a click event can be used to submit a form marked with the ngUpload directive, only that such elements must be marked with the upload-submit css class (as the case with the input[type=submit] above.

The example below uses a styled div to submit the form.

<form action='/server/upload/handler' ng-upload="callbackFunction">
   <!-- other form inputs goes here -->
   <input type="file" name="anyEasyName" />
   <div style="cursor: pointer; padding: 5px" class="upload-submit">Submit</div>
</form>
<div>{{uploadReport}}</div>

You can make your /server/upload/handler spit a valid url, so that {{uploadReport}} can be used to set the src of an <img> tag, like so:

<img ng-src={{uploadReport}} />

and see the uploaded image appear immediately!

The ngController for the above examples is:

var UploadCtrl = function ($scope) {
     $scope.callbackFunction = function(contentOfInvisibleFrame) {
         $scope.uploadReport = contentOfInvisibleFrame;
     }
}

The ngUpload directive can be registered with your AngularJS application module viz:

var mainApp = angular.module('MainApp', ["ngUpload", ...]);

and added to your document as:

<html ng-app="MainApp">

</html>

AngularJS.ngUpload works in the context of a ngController; and such you can have as many uploaders as possible in a single ngController. For example:

<form action='/server/upload/handler' ng-upload="callbackFunction1">
   <!-- other form inputs goes here -->
   <input type="file" name="anyEasyName" />
   <input type="submit" class="upload-submit" value="Submit" />
</form>
Server response: {{uploadReport1}}

<form action='/server/upload/handler' ng-upload="callbackFunction2">
   <!-- other form inputs goes here -->
   <input type="file" name="anotherEasyName" />
   <input type="submit" class="upload-submit" value="Submit" />
</form>
Server response: {{uploadReport2}}

to be served by:

var UploadCtrl = function ($scope) {
     $scope.callbackFunction1 = function(contentOfInvisibleFrame) {
         $scope.uploadReport1 = contentOfInvisibleFrame;
     }

     $scope.callbackFunction2 = function(contentOfInvisibleFrame) {
         $scope.uploadReport2 = contentOfInvisibleFrame;
     }
}

A NodeJS-based upload handler demo of this directive can be found at http://ng-upload.eu01.aws.af.cm.

An ASP.Net MVC and NodeJS sample codes can be found on the project website at github.com/twilson63/ngUpload/tree/master/examples

Hope this helps.

Solution 3 - File Upload

I have put together a simple/light angular directive with polyfill for browsers not supporting HTML5 FormData here:

https://github.com/danialfarid/ng-file-upload

You can send other model object along with the file to the server. Here is the demo page:

http://angular-file-upload.appspot.com/

<script src="angular.min.js"></script>
<script src="ng-file-upload.js"></script>

<div ng-controller="MyCtrl">
  <input type="text" ng-model="myModelObj">
  <input type="file" ngf-select ng-model="files" >
</div>

controller:

Upload.upload({
    url: 'my/upload/url',
    data: {myObj: $scope.myModelObj},
    file: $scope.files
  }).then(function(data, status, headers, config) {
    // file is uploaded successfully
    console.log(data);
  }); 

Solution 4 - File Upload

If you want to handle multiple files, try this

jQuery File Upload Angularjs wrap from the original author (blueimp)

I think it is the most powerful uploader so far.

Solution 5 - File Upload

I recently wrote a directive that supports native multiple file uploads.

Example usage:

<lvl-file-upload
    auto-upload='false'
    choose-file-button-text='Choose files'
    upload-file-button-text='Upload files'
    upload-url='http://localhost:3000/files'
    max-files='10'
    max-file-size-mb='5'
    get-additional-data='getData(files)'
    on-done='done(files, data)'
    on-progress='progress(percentDone)'
    on-error='error(files, type, msg)'/>

You can find the code on github, and the documentation on my blog

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionmkoryakView Question on Stackoverflow
Solution 1 - File UploadBen LeshView Answer on Stackoverflow
Solution 2 - File UploadADEBISI Foluso A.View Answer on Stackoverflow
Solution 3 - File UploaddanialView Answer on Stackoverflow
Solution 4 - File UploadmaxisamView Answer on Stackoverflow
Solution 5 - File UploadJasonView Answer on Stackoverflow