Подтвердить что ты не робот

Загрузка файла стека MEAN

Я создаю веб-приложение стека MEAN, и я хочу загрузить файл, используя ng2-file-upload. Это мой код Angular 2.

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"});

В server.js

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

и в 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});
    });
});

При загрузке файла я получаю следующую ошибку

XMLHttpRequest не может загрузить http://localhost:3000/api/material/create-material. Ответ на запрос предварительной проверки не проходит проверку контроля доступа: значение Заголовок "Access-Control-Allow-Origin" в ответе не должен быть wildcard '*', когда режим учетных данных запроса "include". происхождения 'http://localhost:4200', следовательно, не допускается. режим учетных данных запросов, инициированных XMLHttpRequest, является управляемый атрибутом withCredentials.

В чем причина этого?

4b9b3361

Ответ 1

Добавьте следующее к промежуточному программному обеспечению 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();
});

CORS поддерживает *, нулевой или точный протокол + домен + порт в соответствии с  - > http://www.w3.org/TR/cors/#access-control-allow-origin-response-header

Серверу необходимо будет проверить заголовок источника с помощью регулярного выражения, а затем вы можете эхо-значение исходного значения в заголовке ответа Access-Control-Allow-Origin.

Ответ 2

Проблема здесь заключается в том, что вы запускаете два приложения

  • Angular 2 приложения с номером порта 4200
  • Приложение MEAN stack с номером порта 3000

Поэтому, когда приложение Angular 2 пытается совершить любые вызовы в приложение стека MEAN с номером порта "3000", он будет жаловаться, поскольку он будет рассматриваться как перекрестный домен ajax. Чтобы решить кросс-домен ajax, вам нужно добавить следующие строки кода в ваше приложение стека MEAN.

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();
});

Если вам действительно не нравится это делать, вам нужно сделать следующие шаги.

  • Сначала создайте приложение Angular для развертывания непосредственно в стеке приложения MEAN, используя "ng build".
  • Это приведет к созданию папки "dist" в приложении Angular.
  • Переместите эту папку dist в корневую папку приложения MEAN stack и добавьте следующие строки кода

    app.use(express.static(путь .join(__ dirname, 'dist'), {index: false})); app.get('/', function (req, res) {   res.sendFile(path.join(__ dirname + '/dist/index.html)); });

Выполняя указанные выше шаги, мы запускаем только одно приложение, находящееся под стеком MEAN, а front-end будет обслуживаться из Angular сгенерированной разметки из каталога dist.

Ответ 3

ng2-file-upload имеет возможность указать withcredentials для каждого файла.

Заменить onAfterAddingFile и установить withCredentials = false для каждого файла.

например: this.uploader.onAfterAddingFile = (fileItem:any) => { fileItem.withCredentials = false; }

Это решит вашу проблему. Для получения дополнительной информации: ng2-file-upload/src/file-upload/file-item.class.ts

Ответ 4

Ваш node.js код будет выглядеть следующим образом

var express=require("express");
var multer=require("multer");
var app=express();
var upload=multer({dest:"//destination where you want to upload<folder name>"});
app.post("//routing",upload.single('<variable-name>'),function(req,res){
    console.log("File Uploaded");
});
app.listen(//<port-number>);

Ответ 5

Большинство приведенных ответов здесь верны для реализаций, в которых у вас работает два приложения, и вам нужно установить правильные заголовки CORS, чтобы они могли общаться через браузер. Однако в вашем конкретном случае проблема заключается в том, что вы используете localhost для разработки.

Проблема в том, что Access-Control-Allow-Origin: * не соответствует localhost. Учитывая, что вы задали правильные заголовки CORS для своих запросов OPTIONS, как указывают другие ответы, вы запросите предполетный запрос, вернете правильные заголовки, но хром не подтвердит localhost как допустимый домен, соответствующий *, и будет сбой проверки предполета.

Чтобы решить эту проблему, быстрым решением является добавление поддельного домена в ваш файл hosts, например local.development, а затем укажите этот домен вместо localhost. Теперь вы должны выполнять кросс-исходные запросы.

Ответ 6

Быстрое исправление для localhost:

Используйте расширение Allow-Control-Allow-Origin Chrome, а затем добавьте localhost в список с помощью *

Надеюсь, это поможет.

И попробуйте использовать FormData для загрузки файла. (Angular)

 let formData:FormData = new FormData();  
 formData.append('Document',file);