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?
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.
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.
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.
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
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.
The problem here is you are running two apps
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With