Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

Here is my html form

<form name="myForm" ng-submit="">
    <input ng-model='file' type="file"/>
    <input type="submit" value='Submit'/>
</form>

I want to upload an image from local machine and want to read the content of the uploaded file. All this I want to do using AngularJS.

When I try to print the value of $scope.file it comes as undefined.

share|improve this question
    
what about: stackoverflow.com/questions/12979712/… –  Cherniv Sep 2 '13 at 10:32

9 Answers 9

up vote 108 down vote accepted

Please note that solutions that use FormData(), such as the ones presented here in other answers, do not work correctly in older versions of Internet Explorer. The correct solution should use a backup strategy for that, such as using iframes. There are already many Angular.js modules to perform file uploading:

I would advise you to choose one and use it, or have a look at its code.

share|improve this answer
1  
One more solution (IaaS for file uploading): github.com/uploadcare/angular-uploadcare –  David Avs Oct 10 '14 at 7:25
3  
EggHead has a good video on this - egghead.io/lessons/angularjs-file-uploads –  Adam Zerner Nov 5 '14 at 17:17
20  
Older versions of internet explorer should be left to die. –  fregas Jan 7 at 21:02

Below is working example of file upload:

http://jsfiddle.net/vishalvasani/4hqVu/

In this one function called

setFiles

From View which will update the file array in controller

or

You can check jQuery File Upload using AngularJS

http://blueimp.github.io/jQuery-File-Upload/angularjs.html

share|improve this answer
    
Hi, i was looking for something through which I can just upload one file and display just below it. However in your example I was not able to do same. Dont mind but I am new to this angularjs and my intention to learn to do this particular objective in a simpler yet robust way. –  Aditya Sethi Sep 4 '13 at 14:44
    
This helped a lot. Thanks! –  RachelD Dec 5 '13 at 21:03
    
Excellent example without using an additional library / extension. Thanks. –  markdsievers Apr 5 '14 at 4:01
3  
Very helpful, just a note.. this uses File API which doesn't work in IE9 or below. –  ArjaaAine Jul 18 '14 at 22:21

The easiest is to use HTML5 API, namely FileReader (http://jsfiddle.net/f8Hee/1/).

HTML is pretty straightforward:

<input type="file" id="file" name="file"/>
<button ng-click="add()">Add</button>

In your controller define 'add' method:

$scope.add = function(){
  var f = document.getElementById('file').files[0],
      r = new FileReader();
  r.onloadend = function(e){
    var data = e.target.result;
    //send you binary data via $http or $resource or do anything else with it
  }
  r.readAsBinaryString(f);
}

Note : readAsBinaryString() method is deprecated and readAsArrayBuffer() should be used instead.

share|improve this answer
1  
please explain what is happening here! Whats reader? –  Bhumi Singhal Mar 22 '14 at 18:49
3  
FileReader is a class from standard HTML5 File API w3.org/TR/FileAPI. It allows you to read data from file specified in html input element and process it inside onloadend callback function. You don't need any library to use this API, its already in your browser (unless you use very old one). Hope this helps. –  yagger Mar 23 '14 at 8:18
    
If i need to read an .xls file how can i do it ? –  Bhumi Singhal Mar 23 '14 at 8:19
1  
This is already a different topic. I only can advise you not to use proprietary formats in your app, use de facto standard transition formats CSV or JSON. It has wide support in many JS libraries and custom parser is easy to write and maintain. In case you desperately need to parse almighty .xls, then there are solutions available online, probably very limited. –  yagger Mar 24 '14 at 7:22
3  
FileReader.readAsBinaryString is deprecated as of 12 July 2012 Working Draft from the W3C. –  Shane Stillwell Apr 24 '14 at 13:50

You can achieve nice file and folder upload using flow.js.

https://github.com/flowjs/ng-flow

Check out a demo here

http://flowjs.github.io/ng-flow/

It doesn't support IE7, IE8, IE9, so you'll eventually have to use a compatibility layer

https://github.com/flowjs/fusty-flow.js

share|improve this answer

The blog post at this location (thanks to Jenny Louthan) contains a directive and some sample code. And it just works straight out of the box. The accompanying explanation is very useful.

http://uncorkedstudios.com/blog/multipartformdata-file-upload-with-angularjs

share|improve this answer

http://jsfiddle.net/vishalvasani/4hqVu/ works fine in chrome and IE (if you update CSS a little in background-image). This is used for updating progress bar:

 scope.progress = Math.round(evt.loaded * 100 / evt.total)

but in FireFox angular's [percent] data is not updated in DOM successfully,although files are uploading successfully.

share|improve this answer
    
For FF you can listen to load event and if the length is computable then fire a progress event to indicate the successful upload. github.com/danialfarid/angular-file-upload already takes care of that. –  danial Jan 9 '14 at 7:36
    
It's there, but in given fiddle also it's checked and applied. Still no hope in FF. –  mayankcpdixit Jan 9 '14 at 7:41
    
I think if you just call uploadProgress inside uploadComplete it should work for FF –  danial Jan 9 '14 at 17:47
    
NO it doesn't, and even if it does can you please explain why? I've give a link to fiddle in my post. If possible can you please update it to working in FF and comment solution's link here? –  mayankcpdixit Jan 10 '14 at 5:55
    
What version of Firefox? –  danial Jan 10 '14 at 15:43

I tried all alternatives that @Anoyz (Correct answer) gives... and the best solution is https://github.com/danialfarid/angular-file-upload

Some Features:

  • Progress
  • Multifiles
  • Fields
  • Old browsers (IE8-9)

It's work fine for me. You just have to pay attention to instructions.

In server-side i use NodeJs, Express 4 and Multer middleware to manage multipart request.

share|improve this answer

You may consider IaaS for file upload, such as Uploadcare. There is an Angular package for it: https://github.com/uploadcare/angular-uploadcare

Technically it's implemented as a directive, providing different options for uploading, and manipulations for uploaded images within the widget:

<uploadcare-widget
  ng-model="object.image.info.uuid"
  data-public-key="YOURKEYHERE"
  data-locale="en"
  data-tabs="file url"
  data-images-only="true"
  data-path-value="true"
  data-preview-step="true"
  data-clearable="true"
  data-multiple="false"
  data-crop="400:200"
  on-upload-complete="onUCUploadComplete(info)"
  on-widget-ready="onUCWidgetReady(widget)"
  value="{{ object.image.info.cdnUrl }}"
 />

More configuration options to play with: https://uploadcare.com/widget/configure/

share|improve this answer

Easy with a directive

Html:

<input type="file" file-upload multiple/>

JS:

app.directive('fileUpload', function () {
return {
    scope: true,        //create a new scope
    link: function (scope, el, attrs) {
        el.bind('change', function (event) {
            var files = event.target.files;
            //iterate files since 'multiple' may be specified on the element
            for (var i = 0;i<files.length;i++) {
                //emit event upward
                scope.$emit("fileSelected", { file: files[i] });
            }                                       
        });
    }
};

In the directive we ensure a new scope is created and then listen for changes made to the file input element. When changes are detected with emit an event to all ancestor scopes (upward) with the file object as a parameter.

In your controller:

$scope.files = [];

//listen for the file selected event
$scope.$on("fileSelected", function (event, args) {
    $scope.$apply(function () {            
        //add the file object to the scope's files collection
        $scope.files.push(args.file);
    });
});

Then in your ajax call:

data: { model: $scope.model, files: $scope.files }

http://shazwazza.com/post/uploading-files-and-json-data-in-the-same-request-with-angular-js/

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.