1

i am creating simple file upload module in Angular js(v1.3.4). I am using Nodejs server side. I am using https://github.com/danialfarid/angular-file-upload library. It looks pretty straight forward but i am stuck at the basic step.

index.html

<div ng-controller="FileUploadController">   
        <input type="file" ng-file-select="onFileSelect($files)" multiple>  
</div>

controller.js

  $scope.onFileSelect = function($files) {

                for (var i = 0; i < $files.length; i++) {
                    var file = $files[i];
                    $scope.upload = $upload.upload({
                        url: 'http://localhost:8080/file-transfer/123/upload', 

                       // headers: {'Content-Type': undefined},
                       //     withCredentials: true,
                       //     transformRequest: angular.identity,
                       file: file       
                    }).progress(function(evt) {
                            console.log('percent: ' + parseInt(100.0 * evt.loaded / evt.total));
                        }).success(function(data, status, headers, config) {
                            // file is uploaded successfully
                            console.log(data);
                        });
                }

On Server side, I am using multer for multipart . client is sending the request to server but not sending the file data.

app.all('/file-transfer/:id/upload', function (req, res) {
    res.header('Access-Control-Allow-Credentials', true);
    res.header('Access-Control-Allow-Origin', req.headers.origin);
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
    res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
    console.log(req.body);     // prints - {}
    console.log(req.files);   // prints -  {}
});

Request Header -

Accept  text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding gzip, deflate
Accept-Language en-US,en;q=0.5
Access-Control-Request-Me...    POST
Cache-Control   no-cache
Connection  keep-alive
Host    localhost:8080
Origin  http://localhost
Pragma  no-cache
User-Agent  Mozilla/5.0 (Windows NT 6.2; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0

I used the same code as in example of repository.Maybe i am missing something.

Note - Server codes working fine when i use simple html 5 form without angular or if i use $http.post.

EDIT : It was CORS problem, Read the comments of answer.

NeiL
  • 791
  • 8
  • 35
  • Maybe you need preflight? http://stackoverflow.com/questions/8685678/cors-how-do-preflight-an-httprequest – Paul Jan 07 '15 at 07:35
  • @Paul hey , I just used res.header('Access-Control-Allow-Origin', \'http://localhost'\); Not working , I dont think CORS is an issue. When i send request with $http.post. It works. Problem is in implementation. – NeiL Jan 07 '15 at 07:46
  • there's a very specific list of what you can send or request over CORS without having handler code for preflight/OPTIONS requests in the server. For example, text is OK but application/json is not, even though it is also basically text. I'm wondering if the bare browser uses those, and then when you add angular, it gets changed in angular... – Paul Jan 07 '15 at 07:47

1 Answers1

0

I'm using same library, the only thing different in my client side code is I have the method: 'POST' header being sent:

            $scope.upload = $upload.upload({
                url: '/api/uploads', //upload.php script, node.js route, or servlet url
                // method: 'POST' or 'PUT',
                method: 'POST',
                // headers: {'header-key': 'header-value'},
                // withCredentials: true,
                data: { type: 'profileImage' },
                file: file//, // or list of files: $files for html5 only
                // fileName: 'doc.jpg' or ['1.jpg', '2.jpg', ...] // to modify the name of the file
                /* customize file formData name ('Content-Desposition'), server side file variable name.
                 Default is 'file' */
                //fileFormDataName: myFile, //or a list of names for multiple files (html5).
                /* customize how data is added to formData. See #40#issuecomment-28612000 for sample code */
                //formDataAppender: function(formData, key, val){}
            }).progress(function (e) {
                console.log('percent: ' + parseInt(100.0 * e.loaded / e.total));
            }).success(function (data, status, headers, config) {
                // file is uploaded successfully
                console.log(data);
                $scope.user.profileImages = data;
                $rootScope.$emit('message', { text: "Your profile image has been updated." });
            }).error(function(data){
                if ( data.error === 'UnsupportedFiletype' ) {
                    $rootScope.$emit('message', { type: 'error', text: "Woops, we don't support that filetype." });
                }
            });

Edit: The solution was to just properly serve a cors header:

npm install cors and app.use(cors()).

chovy
  • 72,281
  • 52
  • 227
  • 295
  • 1
    Hey , on which platform you are posting the request server side. because if i use the same code and post the request in .php file , It is printing the $_FILES(able to access the data) . But if i use the nodejs server , I am unable to catch the file data. One more thing ,if i send file data using $http.post on nodejs server. It works fine.That means server is working fine. but this client side code is working fine on .php file . I am not able to catch the error. – NeiL Jan 07 '15 at 10:01
  • I also change the header of server like this res.header('Access-Control-Allow-Credentials', true); res.header('Access-Control-Allow-Origin', 'http://localhost'); res.header('Access-Control-Allow-Methods', 'POST, PUT, OPTIONS'); res.header('Access-Control-Allow-Headers', 'Content-Type'); – NeiL Jan 07 '15 at 10:01
  • `npm install cors` and `app.use(cors())` will make it less ugly. – chovy Jan 07 '15 at 10:10
  • also try `file = req.files.file` to get the file you uploaded. – chovy Jan 07 '15 at 10:12
  • wooo , cors module did the trick. very well.It was cross domain problem.I will tick this. – NeiL Jan 07 '15 at 10:23
  • fyi, you aren't whitelisting. anyone can use your api :) you were writing out the allowed domain that the request was being sent from. If you're going to do that just use `*`. – chovy Jan 07 '15 at 10:25