Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MEAN stack file upload

I am developing a MEAN stack web application and I want to upload file using ng2-file-upload. This is my Angular 2 code.

classroom.component.html

    <input type="file" class="form-control" name="single" ng2FileSelect [uploader]="uploader" />
    <button type="button" class="btn btn-success btn-s"
                  (click)="uploader.uploadAll()" [disabled]="!uploader.getNotUploadedItems().length">
            <span class="glyphicon glyphicon-upload"></span> Upload all
          </button><br />

classroom.component.ts

uploader:FileUploader = new FileUploader({url: "http://localhost:3000/api/material/create-material"});

In server.js

app.use(cors());
app.use('/api',api);
app.use('/api/material',material);

and in material.js

var storage = multer.diskStorage({ //multers disk storage settings
    destination: function (req, file, cb) {
        cb(null, './uploads/');
    },
    filename: function (req, file, cb) {
        var datetimestamp = Date.now();
        cb(null, file.fieldname + '-' + datetimestamp + '.' + file.originalname.split('.')[file.originalname.split('.').length -1]);
    }
});

var upload = multer({ //multer settings
    storage: storage
}).single('file');

router.post('/create-material',passport.authenticate('jwt', {session: false}),function (req, res) {

    upload(req,res,function(err){
        console.log(req.file);
        if(err){
            res.json({error_code:1,err_desc:err});
            return;
        }
        //res.json({error_code:0,err_desc:null});
    });
});

When uploading a file I get following error

XMLHttpRequest cannot load http://localhost:3000/api/material/create-material. Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. Origin 'http://localhost:4200' is therefore not allowed access. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

What is the reason for this?

like image 292
chamathabeysinghe Avatar asked Apr 23 '17 14:04

chamathabeysinghe


People also ask

What is the MEAN stack explain?

The MEAN stack is a JavaScript-based framework for developing web applications. MEAN is named after MongoDB, Express, Angular, and Node, the four key technologies that make up the layers of the stack.

Is MEAN stack scalable?

ScalabilityThe MEAN Stack is ideal for building scalable web applications. It allows developers to add additional features with relative ease. They can do so by running Express on the backend and Angularjs on the frontend.

What is MongoDB in MEAN stack?

MongoDB is a type of NoSQL database that stores documents and collections. The documents are equivalent to records, and the collections are what we know as tables in SQL. So, MongoDB is a database that runs on a server. We store application data there like our users, products, and etc.


3 Answers

ng2-file-upload has option to specify withcredentials for each file.

Override onAfterAddingFile and set withCredentials = false for each file.

eg: this.uploader.onAfterAddingFile = (fileItem:any) => { fileItem.withCredentials = false; }

This will solve your problem. For more details: ng2-file-upload/src/file-upload/file-item.class.ts

like image 151
Jithin Sebastian Avatar answered Oct 17 '22 03:10

Jithin Sebastian


Add following to your nodejs middleware -

app.use(function (req, res, next) {
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
    res.setHeader('Access-Control-Allow-Credentials', true);

    next();
});

The CORS supports *, null or the exact protocol + domain + port as per -> http://www.w3.org/TR/cors/#access-control-allow-origin-response-header

Server will need to validate the origin header using the regex, and then you can echo the origin value in the Access-Control-Allow-Origin response header.

like image 30
AJS Avatar answered Oct 17 '22 01:10

AJS


The problem here is you are running two apps

  1. Angular 2 app with port number 4200
  2. MEAN stack app with port number 3000

So when Angular 2 app tries to do any calls to MEAN stack app which has port number "3000" browser will complain as it will be treated as cross domain ajax. To solve the cross domain ajax you will have to add the following lines of code in your MEAN stack app.

app.use(function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    next();
});

If you really dont like doing this, then you have to do following steps.

  1. First build the angular app to deploy directly under MEAN stack app using "ng build".
  2. This will generate "dist" folder in angular app.
  3. Move this dist folder under root folder of MEAN stack app and add following lines of code

    app.use(express.static(path.join(__dirname, 'dist'), {index: false}));
    app.get('/', function (req, res) { res.sendFile(path.join(__dirname + '/dist/index.html')); });

By doing the above steps we are running only one app that is under MEAN stack and front-end will be served from angular generated markup from dist folder.

like image 3
HumbleGeek Avatar answered Oct 17 '22 02:10

HumbleGeek