Estoy desarrollando una aplicación web MEAN stack y quiero cargar un archivo usando ng2-file-upload. Este es mi código Angular 2.
aula.componente.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 />aula.componente.ts
uploader:FileUploader = new FileUploader({url: "http://localhost:3000/api/material/create-material"});En servidor.js
app.use(cors()); app.use('/api',api); app.use('/api/material',material);y en 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}); }); });Al subir un archivo me sale el siguiente error
XMLHttpRequest no puede cargar http://localhost:3000/api/material/create-material . La respuesta a la solicitud de verificación previa no pasa la verificación de control de acceso: el valor del encabezado 'Access-Control-Allow-Origin' en la respuesta no debe ser el comodín '*' cuando el modo de credenciales de la solicitud es 'incluir'. Por lo tanto, no se permite el acceso al origen ' http://localhost:4200 '. El modo de credenciales de las solicitudes iniciadas por XMLHttpRequest está controlado por el atributo withCredentials.
¿Cuál es la razón para esto?
Agregue lo siguiente a su middleware nodejs:
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(); });El CORS admite *, nulo o el protocolo exacto + dominio + puerto según -> http://www.w3.org/TR/cors/#access-control-allow-origin-response-header
El servidor deberá validar el encabezado de origen mediante la expresión regular, y luego podrá hacer eco del valor de origen en el encabezado de respuesta Access-Control-Allow-Origin.
El problema aquí es que estás ejecutando dos aplicaciones.
Entonces, cuando la aplicación Angular 2 intente hacer llamadas a la aplicación MEAN stack que tiene el número de puerto "3000", el navegador se quejará, ya que será tratado como ajax de dominio cruzado. Para resolver el ajax de dominio cruzado, deberá agregar las siguientes líneas de código en su aplicación MEAN stack.
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(); });Si realmente no te gusta hacer esto, entonces tienes que seguir los siguientes pasos.
Mueva esta carpeta dist debajo de la carpeta raíz de la aplicación MEAN stack y agregue las siguientes líneas de código
app.use(express.static(path.join(__dirname, 'dist'), {index: false}));
app.get('/', function (req, res) { res.sendFile(path.join(__dirname + '/dist/index.html')); });
Al realizar los pasos anteriores, estamos ejecutando solo una aplicación que se encuentra en la pila MEAN y el front-end se servirá desde el marcado angular generado desde la carpeta dist.
ng2-file-upload tiene la opción de especificar withcredentials para cada archivo.
onAfterAddingFile y establezca withCredentials = false para cada archivo.
por ejemplo: this.uploader.onAfterAddingFile = (fileItem:any) => { fileItem.withCredentials = false; }
Esto resolverá tu problema. Para más detalles: ng2-file-upload/src/file-upload/file-item.class.ts