Git Product home page Git Product logo

angular-upload's Introduction

Angular Upload

Upload files using FormData, fall back to iframe upload when FormData isn't supported

  • Works in all browsers
  • Lightweight
  • No dependency on jQuery

Example

<div
  class="btn btn-primary btn-upload"
  upload-button
  url="/upload"
  on-success="onSuccess(response)"
>Upload</div>

Install

Install via bower

bower install --save angular-upload

Add the module to your app dependencies and include it in your page

angular.module('app', [
  'lr.upload'
]);
<script src='bower_components/angular-upload/angular-upload.min.js'></script>

and to your less/css if you want the upload button

@import "bower_components/angular-upload/src/directives/btnUpload.less"; /* or .min.css */

And you are good to go!

Documentation over parameters

Upload button

The upload button masks the normal file input and makes it look like a button

<div
  class="btn btn-primary btn-upload"
  upload-button

  // Mandatory, the url of the backend that is going to handle the upload
  url="/upload"

  // Optional, file param name for upload
  param="file"

  // Optional, object to send as form data with the upload
  data="formData"

  // Optional, comma separated list or array of allowed mimetypes, defaults to allowing all types
  accept="{{acceptTypes}}"

  // Optional, Allow selecting multiple files, defaults to false
  multiple="{{allowMultiple}}"

  // Optional, force all uploads through the iframe solution, defaults to false and should normally not be included
  force-iframe-upload="{{forceIframeUpload}}"

  // Optional, make file input required and add ng-invalid-required if required is set to true on the input button
  required="true|false"

  on-upload="onUpload(files)" // Optional callback when uploading starts
  on-success="onSuccess(response)" // Optional callback
  on-error="onError(response)" // Optional callback
  on-complete="onComplete(response)" // Optional, callback (called on both on-success and on-error)

>Fileupload</div>

Advanced documentation

The upload service that is used behind the scenes in the upload button, can be used in a controller by injecting upload

<body ng-app="app" ng-controller="AppCtrl">
    <input name="myFile" type="file" />
</body>
angular.module('app').controller('AppCtrl', function ($scope, upload) {
  $scope.doUpload = function () {
    upload({
      url: '/upload',
      method: 'POST',
      data: {
        anint: 123,
        aBlob: Blob([1,2,3]), // Only works in newer browsers
        aFile: $scope.myFile, // a jqLite type="file" element, upload() will extract all the files from the input and put them into the FormData object before sending.
      }
    }).then(
      function (response) {
        console.log(response.data); // will output whatever you choose to return from the server on a successful upload
      },
      function (response) {
          console.error(response); //  Will return if status code is above 200 and lower than 300, same as $http
      }
    );
  }
});

Build it yourself!

angular-upload is built with grunt and has a express backend for testing.

Start by installing npm if you don't have it already

via homebrew or homepage (http://nodejs.org/download/)

brew install nodejs

then

npm install -g grunt-cli karma-cli

then from within angular-upload

npm install && bower install

then you can start the testserver up with

grunt webserver

and you can access it through http://localhost:9001 and test the uploader

To run the tests

grunt test

or run in autotest mode

grunt autotest

And when you're done minify it

grunt package

angular-upload's People

Contributors

cxn-astracz avatar falci avatar gschuager avatar leon avatar marcelinhov2 avatar slobo avatar xiongliding avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

angular-upload's Issues

Thank you

Thanks for putting the bower_component include in the readme.

How can I hide the Choose File button?

I expect the button css to be fully controlled by me. When I click on the button, a file chooser dialog should pop up. So is there any way I can hide the Choose File button? Thanks.

angular-upload not work IE9

Here is my html:

angular.module('MyApp', ['lr.upload']);

<script src="/mm/js/devel/modules/angular-upload.js"></script>
UPLOAD

But not work only with IE9 in console i find this error:
Failed to instantiate module lr.upload due to:
[$injector:nomod] Module 'lr.upload' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.
http://errors.angularjs.org/1.2.25/$injector/nomod?p0=lr.upload
http://errors.angularjs.org/1.2.25/$injector/modulerr?p0=lr.upload&p1=%5B%24injector%3Anomod%5D%20Module%20'lr.upload'%20is%20not%20available!%20You%20either%20misspelled%20the%20module%20name%20or%20forgot%20to%20load%20it.%20If%20registering%20a%20module%20ensure%20that%20you%20specify%20the%20dependencies%20as%20the%20second%20argument.%0Ahttp%3A%2F%2Ferrors.angularjs.org%2F1.2.25%2F%24injector%2Fnomod%3Fp0%3Dlr.upload
http://errors.angularjs.org/1.2.25/$injector/modulerr?p0=BffApp&p1=%5B%24injector%3Amodulerr%5D%20F

Can you help me ?
Many thanks

Upload on IE9

Hi all!
When the file upload directive is rendered within IE9, the onUpload function does not get called.

fileInput[0].files is undefined in the line below.

              scope.$apply(function () {
                  scope.onUpload({ files: fileInput[0].files });
              });

do you have a solution for this?

thanks!
cenk

IE9

Hello!

Maybe anyone has any pointers of where to look.

Basically, when doing IE9 upload, it uses IFRAME method and upload does not work. I tracked that it calls form[0].submit, but nothing actually goes to server (using IE9 compatiblity mode, will try normal IE9 when i have chance).

UPDATE: Hmm, seems that i was blind, it is actually sending with no problems, and this is CSRF token issue, seems that i have find a way to append CSRF header to IFRAME method.

Progress status?

Hi, my question is pretty straight forward. How do i add progress status?
I already tried modifying the angular-upload.js by adding log in on success and on error function. but that does not work

Upload of multipart file

Hi @leon ,

When uploading any file other than a text file, the upload window gets stuck.
Please find the code below

                 <div class="btn btn-primary btn-upload"
                    style="width: 120px; z-index: auto;" upload-button
                    url="/properties/upload"
                    required="true"
                    accept="text/plain multipart"
                    on-success="uploadSuccess1(response)">Upload File</div>

I have to upload only text files, is there a way to limit the upload functionality to that alone. Also it should give a proper message if its an incorrect format.

Obsolete code since for angular 1.3+

Hi recently migrate angular framework in my project from 1.2.28 to 1.4.7
And found that since this commit angular/angular.js@7b6c1d0#diff-748e0a1e1a7db3458d5f95d59d7e16c9

angular changed their default response interceptor, now they require headers link

in upload code when you use force Iframe option,
https://github.com/leon/angular-upload/blob/master/angular-upload.js#L254
iframe doesn't has headers for you try to call interceptor with Array instead of function.

angular defaultHttpResponseTransform fall with Uncaught TypeError: headers is not a function(…)
and as soon as in upload you call all transformation in try{}catch(){} https://github.com/leon/angular-upload/blob/master/angular-upload.js#L215
you will never see this error, but you also never get proper JSON response from angular interceptor.

suggested fix:
change https://github.com/leon/angular-upload/blob/master/angular-upload.js#L252
to

var headers = function(){}; // not sure is there any sense return anything for iframe 

P.S. up to you if you want change anything. I guess people who use you library parse json response manually

button not clickable in large browser windows

open a large chrome window, e.g. 1800px width, and try to click the "upload-button".
you can only reach the button on the right ~half of the screen.
fixed it by overwriting a style:
.btn-upload input {
right: auto;
left: 0;
}
this seems to work for me
cheers

Need clarification on <upload-button> parameters.

The document is little bit unclear of whether the parameters are taken as literal string or value from $scope unless I look into the code. It would be nice if the README.md could clarify that.

Thank you.

Access-Control-Allow-Origin

Hi,

I've some issues with Access-Control-Allow-Origin using the angular-upload component.

Is any configuration required to use in differents domains?

I'm trying to upload from localhost:8000 to localhost:3000

Thanks!!

IE9 - Returning a non-200 code from the server causes "Access Denied"

I'm using this on a site that needs to be IE9 compatible and noticed an issue recently:

If you return an error code during the upload, for example 400 Bad Request then IE replaces the contents of the iframe with it's own error message (at this URI res://ieframe.dll/http_500.htm). This changes the domain of the iframe, and the following line fails:

var doc = this.contentWindow ? this.contentWindow.document : this.contentDocument;

This makes response null, and the promise to return null for the data property.

The workaround I had to do was to return a 200 from the server and then check my JSON response for an error property.

I am not sure if there is even a way around this, so maybe it should just be an update to the docs noting that the server should return 200 always, and error handling is up to the angular code?

Thanks!

IE iframe upload sending always http response status 200

When we try to submit a form with an angular-upload element, then in case there is an exception generated by the server which returns an http status 500, but since in IE the upload is taking place through the iframe, the angular-upload directive is always returning the http status to 200 due to which the responseError interceptor is not getting invoked. Kindly check and fix this issue. Thanks.

Binary file not uploading properly

I'm using this jade on the client side

   div(
        class="btn btn-primary btn-upload"
        upload-button
        url="/api/gps"
        method="POST"
        required="true"
        on-success="onSuccess(response)" 
    ) Fileupload

And receive in nodejs with

exports.receive = function(req, res) {
    var fitFileBuffer = new Buffer('');
    req.on('data', function(chunk) { 
        fitFileBuffer = Buffer.concat([fitFileBuffer, chunk]);
    });
    req.on('end', function() { 
        fs.writeFileSync(
            "server/api/gps/today2.fit",
            fitFileBuffer);

When I upload today.fit (from a GPS) and compare with today2.fit that is saved, then it is clearly not the same final that is saved. What am I doing wrong?

Module does not work with ng-model.

I will like to have the name of the file in my controller but your module doesn't support this! Am I missing something in the docs or I need to create my own directive to support this.

Add id at the input file

I think the directive need to automatic add an id to the input file. That way, I can add a label with a "for" parameter to open the "directory" screen.

In my conception, we can mount this feature using the ID of the upload-button + "_input". That way, we will not have 2 equals id's in the screen and we will reach the needed feature.

when using upload existing headers are overwritten

In formDataUpload the config parameter is extended to add the 'Content-Type': undefined header

If I try to use upload with a custom header, like:

          headers: {'X-HTTP-Method-Override': 'PATCH'},
          url: config.api + '/games/' + this.data.slug + '/',
})```

my header is overwritten by

return $http(angular.extend(config, {
headers: { 'Content-Type': undefined },
transformRequest: formDataTransform
}));


I'm working on a fix

cancelling

Any ideas on how cancelling an iframe upload would work?

on-begin-uploading attribute on uploadButton directive

It would be nice to have a callback to execute at the beginning of an upload when using the uploadButton directive (I know I can use the upload service manually).

If you agree, I can give a try at implementing this and sending you a PR.

Video File

Uploading Video files returns 400 bad request.

multiple property is not supported ?

I don't get the input html tag with multiple property

This is my code:

<div class="btn btn-danger btn-block btn-upload" upload-button url="/php/up.php?{{params}}" param="images" data="formData" multiple="true" required="true" on-upload="function1()" on-success="function2(response)" on-error="function3(response)">
   <h5>اختر الصور</h5>
</div>

This is what I get:
<input type="file" required="required">

IE9 - Browser tries to download JSON

Hi there!

I recently started implementing your solution because uploading files on IE9 is a nightmare.
With your solution, it seems to upload the selected file, but when I get a response back from the server (returns a json), IE9 tries to download the file and it doesn't trigger any of the callbacks there are. Only "onUpload" callback is being called but with no arguments.

Is there anything I can do so that my this returns a json instead of trying to download the file?

Thank you in advance!

Nothing happends when you click button.

I'd like that when the whole upload button is clicked, then it will show the filechooser dialog. Right now as it is, it only happens if the input field is clicked, maybe others would as well

element.on('click', function() {
var children = this.childNodes;
if (children.length > 0) {
for (var i = 0; i < children.length; i++)
if (children[i].type==="file") {
children[i].click();
}
}
});

directive link, under el.append(fileInput)

required=true not working as I would expect it to

I apologize in advance if I don't understand what required=true is supposed to do, but it seems to me like it should be the same as just adding the "required" attribute for other elements such as textarea.

When I do this:

<form name="myForm" novalidate>
  <textarea ng-model="someText" required>
  <button type="submit" class="btn btn-primary" ng-disabled="myForm.$invalid">Submit</button>
</form>

The submit button will be disabled until I put something in the textarea.

However if I do this:

<form name="myForm" novalidate>
    <div
      class="btn btn-primary btn-upload"
      url="/api/documents"
      param="file"
      required="true"
      upload-button>Upload</div>
  <button type="submit" class="btn btn-primary" ng-disabled="myForm.$invalid">Submit</button>
</form>

Then I can press "Submit" just fine even when there's no file selected.

Of course you'll see I added novalidate, but the point still stands, because even in the official AngularJS guide to forms (https://docs.angularjs.org/guide/forms) they always use novalidate on the form and everything works (as Angular then takes over the job of applying validations from the browser). Does this make sense?

How to handle uploaded file on the server?

I'm afraid I don't understand how to access the file on the server. Should I be able to access it from the req object somewhere, does it get saved on the server, or is it something else?

Thanks in advance!

Error: I get status as -1

Hi Leon,

I have been using this element and was working fine. All my code (app, controller and service) were in the same file. Then I organized my code so that app, controllers and services are placed in a separate js file. After this I started receiving the onerror callback. On checking I see status value as -1. I don't see any other error information and not sure what went wrong and what needs to be fixed. Can you please guide how to diagnose this issue?

<upload-button class="btn btn-upload" url="/angularperson/editImage" param="personImage" accept="image/*" multiple="false" force-iframe-upload="false"
                                data="person" on-upload="onUpload(files)" on-success="onGlobalSuccess(response)" 
                                on-error="onError(response)" on-complete="onComplete(response)"></upload-button>

Thanks,
Hemant.

Upload triggered from controller is not working

If you trigger upload from controller as it is shown in the Advanced example, firstly it will trigger undefined method to server.
To fix that, you must add this line to the options: method: 'POST'

After that, upload function still ignores given file - I had to change your example to this to make it work:

HTML:

Upload function usage:
upload({
url: '/api/advert',
method:"POST", // added method
data: {
anint: 123,
file: $("#myFile"), // specified DOM element or jquery object with DOM element
}
}).then(
function (response) {
alert(response.data);
},
function (response) {
alert(response.toSource());
}
);

Please update your example..

(Using Firefox 29.0, Ubuntu Linux)

data parameter doesnt work

 <div
            class="btn btn-primary btn-upload"
            upload-button
            url="/fileupload"
            param="uploadedFile"
            data="{{location}}"
            on-success="onSuccess(response)"
            >
        Upload
    </div>

writing like below doesn't work either

<div
            class="btn btn-primary btn-upload"
            upload-button
            url="/fileupload"
            param="uploadedFile"
            data="location"
            on-success="onSuccess(response)"
            >
        Upload
    </div>

location is $scope.location. I tries to put an object there or string. In the server the body and.or query is empty

Capture from camera

I like suggest add a capture=camera to project. I like use it in mobile projects.

Is it correct that Content-Type equals false?

I can't seem to upload a file to a .NET backend with this tool but I actually can with a similar one, and looking at the requests in Chrome dev tools I noticed that the successful request includes the following header:
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryvRHAWeTpJaJ6BKgO
instead of the
Content-Type:false
that is issued by this tool.

Do you have any hint about what's going on?

CommonJS support please

We are using webpack and trying to inject this module like:

import angularUploadModule from 'angular-upload';

//...

export default angular
    .module('states.blog.edit', [
        angularUploadModule,
        // ...
    ])
    .name;

But 'package.main' file does not export anymore.

Please, export the module or .name for better modularity.

order of form elements in iframe upload preventing uploader working with aws

Hi, I'm using your uploader to upload files to S3. I ran into some problems along the way. One them them, is that s3 requires the file element to be last in the upload element:

http://docs.aws.amazon.com/AmazonS3/latest/dev/HTTPPOSTForms.html

"The file or content must be the last field in the form. Any fields below it are ignored."

I was able to alleviate this problem by swapping the order that the elements are attached in this code:

        angular.forEach(files, function (input) {
          var clone = input.clone(true);
          input.after(clone);
          form.append(input);
        });
        angular.forEach(config.data, function (value, name) {
          var input = angular.element('<input type="hidden" />');
          input.attr('name', name);
          input.val(value);
          form.append(input);
        });

I assume there's no other reason, why files would need to be first? I can submit a pull request for the change.

arraybuffer response problem after upload

hi,

there is a problem when byte array is returned on response after uploading file. i use this for excel files. for a stuation, i upload an excel file and another excel data is returned in response as arraybuffer. bu if you dont set an responseType:"arraybuffer" property on "options" object, it doesnt create a valid excel file. for that, i did a modification;

i added this to params;

isArrayBuffer : '@' // ADDED BY FATIH POLATLI

and added this under options object;

// ADDED BY FATIH POLATLI

        if(scope.isArrayBuffer === true || scope.isArrayBuffer === 'true'){

          options.responseType = "arraybuffer";
        }
        //

you can set it as attribute now and it works;

is-array-buffer="true";

it may be good to add this to project if you want.

thanks

install / server.js problem

Bower install ends up with 👍
bower resolve git://github.com/twbs/bootstrap.git#~3.0.0
bower ECMDERR Failed to execute "git ls-remote --tags --heads git://github.com/aFarkas/html5shiv.git", exit code of #128

node server.js ends up with 👍
connect.multipart() will be removed in connect 3.0
visit https://github.com/senchalabs/connect/wiki/Connect-3.0 for alternatives
connect.limit() will be removed in connect 3.0

regards

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.