file uploader integration for angularjs [closed]
Solution 1:
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:
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:
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);
});