2

I'm trying to implement this library to upload images to a folder server:

When I click on "upload" button the server returns inmediately to the listener this.uploader.onCompleteItem on my fileUpload.ts component:

ImageUpload:uploaded: FileItem {url: "http://127.0.0.1:5000/api/uploadPhoto", headers: Array(0), withCredentials: false, formData: Array(0), isReady: false…}alias: "file"file: FileLikeObjectformData: Array(0)headers: Array(0)index: undefinedisCancel: falseisError: falseisReady: falseisSuccess: trueisUploaded: trueisUploading: falsemethod: "POST"options: ObjectautoUpload: falsedisableMultipart: falsefilters: Array(1)isHTML5: trueitemAlias: "file"removeAfterUpload: falseurl: "http://127.0.0.1:5000/api/uploadPhoto"__proto__: Objectprogress: 100some: Fileuploader: FileUploaderurl: "http://127.0.0.1:5000/api/uploadPhoto"withCredentials: false_file: File_xhr: XMLHttpRequest__proto__: Object 200 "uploaded"

But the file is not present on server. What would be doing wrong?

This is my backend: Server.js

     var express     = require("express"),
            app             = express(),
            cors            = require('cors'),
            bodyParser      = require("body-parser"),
            methodOverride  = require("method-override"),
            http            = require("http"),
            multer          = require('multer');
            server          = http.createServer(app),
            router          = express.Router()
                .....
                app.use(function (req, res, next) {
                res.header("Access-Control-Allow-Methods", "POST, PUT, OPTIONS, DELETE, GET");
                res.header('Access-Control-Allow-Origin', 'http://localhost:3000');
                res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
                res.header("Access-Control-Allow-Credentials", true);
                next();
            });
          //NEW
          app.use(bodyParser.urlencoded({extended: false}));
          app.use(bodyParser.json());
          app.use(cors());
          app.use(methodOverride());
          app.use(passport.initialize());
          app.use(busboyBodyParser());
          //
          app.use('/api', router);


                var upload = multer({dest: "./uploads/"}).single('file');


                router.post("/uploadPhoto",function (req, res) {
                        upload(req, res, function (err) {
                            if (err) {
                                console.log(err.toString())
                                return res.status(422).json("an Error occured")
                            }
                            console.log("done")
                            return res.status(200).json("uploaded")
                        })
                    }

                    );

This is my Frontend

fileUpload.ts

import { FileUploader } from 'ng2-file-upload';
...

public uploader:FileUploader;
constructor() {

        this.uploader  = new FileUploader({url: this.URL + "uploadPhoto", itemAlias: 'file'});

        this.uploader.onBeforeUploadItem = (item) => {
            item.withCredentials = false;
        }

        this.uploader.onCompleteItem = (item:any, response:any, status:any, headers:any) => {
            console.log("ImageUpload:uploaded:", item, status, response);
        };

    }

fileUpload.html

....
  <input name="file" type="file" ng2FileSelect [uploader]="uploader"/>

<button type="button" class="btn btn-success btn-xs"
                                    (click)="item.upload()" [disabled]="item.isReady || item.isUploading || item.isSuccess">
                                <span class="glyphicon glyphicon-upload"></span> upload
                            </button>
.....

Systemjs.config.js

(function (global) {
  System.config({
    paths: {
      // paths serve as alias
      'npm:': 'node_modules/'
    },
    // map tells the System loader where to look for things
    map: {
      // our app is within the app folder
      app: 'app',

      // angular bundles//
      '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
      '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
      '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
      '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
      '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
      '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
      '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
      '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',


      // other libraries
      'rxjs':                       'npm:rxjs',
      '@angular/material': 'npm:@angular/material/bundles/material.umd.js',
      'hammerjs': 'npm:hammerjs/hammer.js',
      'ngx-sharebuttons': 'node_modules/ngx-sharebuttons/bundles/ngx-sharebuttons.umd.js',
      'ngx-cookie': 'npm:ngx-cookie/bundles/ngx-cookie.umd.js',
       'ng2-file-upload': 'npm:ng2-file-upload',
      '@agm/core': 'node_modules/@agm/core/core.umd.js',
       '@angular/animations': 'node_modules/@angular/animations/bundles/animations.umd.min.js',
       '@angular/animations/browser':'node_modules/@angular/animations/bundles/animations-browser.umd.js',
       '@angular/platform-browser/animations': 'node_modules/@angular/platform-browser/bundles/platform-browser-animations.umd.js'
//

    },
    // packages tells the System loader how to load when no filename and/or no extension
    packages: {
      app: {
        main: './main.js',
        defaultExtension: 'js'
      },
        rxjs: {
            defaultExtension: 'js',
            main: 'Rx.js'
        },
        'ng2-file-upload': {
            main: 'ng2-file-upload.js',
            defaultExtension: 'js'
        }
    }
  });
})(this);

app.module

import { FileSelectDirective, FileDropDirective } from 'ng2-file-upload';
....
declarations:[FileSelectDirective,.....

package.json of my frontend

{
  "name": "angular2-quickstart",
  "version": "1.0.0",
  "scripts": {
    "start": "tsc && concurrently \"npm run tsc:w\" \"npm run lite\" ",
    "lite": "lite-server",
    "postinstall": "typings install",
    "tsc": "tsc",
    "tsc:w": "tsc -w",
    "typings": "typings"
  },
  "license": "ISC",
  "dependencies": {
    "@agm/core": "^1.0.0-beta.0",
    "@angular/animations": "^4.1.2",
    "@angular/common": "4.1.3",
    "@angular/compiler": "4.1.3",
    "@angular/compiler-cli": "4.1.3",
    "@angular/core": "4.1.3",
    "@angular/forms": "4.1.3",
    "@angular/http": "4.1.3",
    "@angular/material": "2.0.0-beta.5",
    "@angular/platform-browser": "4.1.3",
    "@angular/platform-browser-dynamic": "4.1.3",
    "@angular/router": "4.1.3",
    "@angular/upgrade": "4.1.3",
    "body-parser": "^1.15.2",
    "bootstrap": "^3.3.6",
    "core-js": "^2.4.1",
    "express": "^4.14.0",
    "hammerjs": "^2.0.8",
    "method-override": "^2.3.6",
    "ng2-file-upload": "^1.2.0",
    "ngx-cookie": "^1.0.0",
    "ngx-sharebuttons": "^3.0.0",
    "node-sass": "^4.5.0",
    "reflect-metadata": "^0.1.3",
    "rxjs": "5.4.0",
    "systemjs": "0.20.12",
    "zone.js": "^0.8.5"
  },
  "devDependencies": {
    "@types/hammerjs": "^2.0.34",
    "concurrently": "^3.2.0",
    "lite-server": "^2.2.2",
    "typescript": "^2.1.6",
    "typings": "^2.1.0"
  }
}

package.json backend

{
  "name": "Backend",
  "version": "0.0.0",
  "description": "Generated with Eclipse npm Tools",
  "main": "index.js",
  "author": "",
  "license": "ISC",
  "dependencies": {
    "agenda": "^0.9.1",
    "async": "^2.3.0",
    "bluebird": "^3.4.7",
    "body-parser": "^1.16.1",
    "busboy-body-parser": "^0.3.0",
    "crypto": "0.0.3",
    "email-verification": "^0.4.6",
    "express": "^4.14.1",
    "gridfs-stream": "^1.1.1",
    "method-override": "^2.3.7",
    "mongoose": "^4.8.5",
    "multer": "^1.3.0",
    "mysql": "^2.11.1",
    "nconf": "^0.8.4",
    "oauth2orize": "^1.7.0",
    "passport": "^0.3.2",
    "passport-http": "^0.3.0",
    "passport-http-bearer": "^1.0.1",
    "passport-oauth2-client-password": "^0.1.2"
  }
}

EDIT2:

I've half solved the problem with this:

    var express     = require("express"),
                app             = express(),
                cors            = require('cors'),
                bodyParser      = require("body-parser"),
                methodOverride  = require("method-override"),
                http            = require("http"),
                multer          = require('multer');
                server          = http.createServer(app),
                router          = express.Router()
                    .....
                    app.use(function (req, res, next) {
                    res.header("Access-Control-Allow-Methods", "POST, PUT, OPTIONS, DELETE, GET");
                    res.header('Access-Control-Allow-Origin', 'http://localhost:3000');
                    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
                    res.header("Access-Control-Allow-Credentials", true);
                    next();
                });


    var storage = multer.diskStorage({
        destination: function (req, file, cb) {
            cb(null, './uploads/')
        },
        filename: function (req, file, cb) {
            console.log("aha " + file.originalname);
            cb(null, file.originalname)
        }
    })


    var upload = multer().single('file')

    //THIS IS MANDATORY, WITHOUT THIS NOW WORK
    app.use(multer({
     storage:storage
     }).single('file'));


              app.use(bodyParser.urlencoded({extended: false}));
              app.use(bodyParser.json());
              app.use(cors());
              app.use(methodOverride());
              app.use(passport.initialize());
              app.use(busboyBodyParser());
              //
              app.use('/api', router);


router.post("/uploadPhoto", function(req, res) {
    console.log(req.file);
    upload(req,res,function(err){
        if(err){
            res.status(500).json({'success':false});
            return;
        }
        res.status(200).json({'success':true});
    });
});

The app.use(multer({storage:storage}).single('file')); appears to be the key. But I pretty new and I dont know why

Also With 'multiple' and .array('file',12) isn't work

I've founded a related question on multer github page with the same problem

Hanzo
  • 1,839
  • 4
  • 30
  • 51
  • Where are you seeing `When I click on "upload" button the server returns` the value `ImageUpload:uploaded: FileItem {u...`? – bhantol May 24 '17 at 17:36
  • On the console of browser. This log is emitted by the onCompleItem listener that is defined on component. – Hanzo May 24 '17 at 18:02
  • Totally missed that console.log. Posted what I think may be missing. Assumption is that it is missing and does not exist in those `.....` – bhantol May 24 '17 at 18:49
  • I've added more info to original message, the `....` means code that is irrelevant to this question and could add noise to the question. Thanks for your time – Hanzo May 25 '17 at 08:18
  • I deleted my answer after I was able to make sure that your backend code was fine. In short with your exact same backend code I am able to make everything. The only thing I had to do was add proxy for CORS. You need those headers for the app that server angular. If using angular-cli try --proxy – bhantol May 25 '17 at 16:55
  • Thanks. I've added all app.uses to my code of the original server.js message. Could you guide what I should add to cors confguration? Thanks for all – Hanzo May 25 '17 at 17:08
  • When I tried your code I got cors errors which got fixed by adding proxy on the angular app. So you need cors on the angular app that is serving index.html – bhantol May 25 '17 at 18:20
  • Where you see the error with cors? I don't have any errors, the only error y that the file is not present on server. When i press the button 'upload' the request arrives to `console.log("done")` point on my server. Both, frontend and backend are on the same machine, macos x with ports 3000 for front and 5000 to back. I've updated the first message with packages.json, systemjs.... THANKS – Hanzo May 25 '17 at 21:05
  • I've added to my first message a `EDIT2` where shows a way to do it. – Hanzo May 26 '17 at 10:19
  • Using code I saw those cors errors on the console in chrome. When you use different port it can break the CORS. The static files that are served from the port 3000 needs to set the cors headers to allow 5000. Good luck. – bhantol May 30 '17 at 02:06

0 Answers0