MEAN堆栈文件上传

时间:2017-04-23 14:08:30

标签: javascript node.js angular mean-stack

我正在开发一个MEAN堆栈Web应用程序,我想使用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。回应   预检请求没有通过访问控制检查:的值   &#39;访问控制允许来源&#39;响应中的标题不能是   通配符&#39; *&#39;当请求的凭据模式为&#39; include&#39;时。起源   &#39; http://localhost:4200&#39;因此不允许访问。该   XMLHttpRequest发起的请求的凭证模式是   由withCredentials属性控制。

这是什么原因?

7 个答案:

答案 0 :(得分:10)

将以下内容添加到您的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支持*,null或精确的协议+域+端口   - &GT; http://www.w3.org/TR/cors/#access-control-allow-origin-response-header

服务器需要使用正则表达式验证原始标头,然后您可以在Access-Control-Allow-Origin响应标头中回显原始值。

答案 1 :(得分:3)

这里的问题是你正在运行两个应用程序

  1. Angular 2 app,端口号为4200
  2. 端口号为3000的MEAN堆栈应用
  3. 因此,当Angular 2应用程序尝试对MEAN堆栈应用程序进行任何调用时,该应用程序具有端口号&#34; 3000&#34;浏览器会抱怨,因为它将被视为跨域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();
    });
    

    如果您真的不喜欢这样做,那么您必须执行以下步骤。

    1. 首先构建角度应用程序,使用&#34; ng build&#34;直接在MEAN堆栈应用下部署。
    2. 这会产生&#34; dist&#34;角应用程序中的文件夹。
    3. 将此dist文件夹移动到MEAN堆栈应用程序的根文件夹下,并添加以下代码行

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

    4. 通过执行上述步骤,我们只运行一个位于MEAN堆栈下的应用程序,前端将通过dist文件夹中的角度生成标记提供服务。

答案 2 :(得分: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

答案 3 :(得分:2)

您的 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>);

答案 4 :(得分:2)

这里给出的大多数答案都适用于您运行两个应用程序并且需要设置正确的CORS标头以便它们可以通过浏览器进行通信的实现。但是,在您的特定情况下,问题是您使用localhost进行开发。

问题在于Access-Control-Allow-Origin: * doesn't match localhost。如果您已根据其他答案的建议为OPTIONS请求设置了正确的CORS标头,则您的预检请求将返回正确的标头,但Chrome不会确认{ {1}}作为匹配localhost的有效域,并且将无法进行预检检查。

要解决此问题,快速解决方案是将假域添加到您的主机文件(例如*),然后指向此域而不是local.development。您现在应该可以使用跨域请求。

答案 5 :(得分:0)

本地主机快速修复:

使用 Allow-Control-Allow-Origin Chrome扩展程序,然后使用*

在列表中添加本地主机

希望这会有所帮助。

并尝试使用FormData进行文件上传。(角度)

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

答案 6 :(得分:-1)

也许这会有所帮助:

No 'Access-Control-Allow-Origin' - Node / Apache Port Issue

通配符Access-Control-Allow-Origin只是放了一个“*”而不是“http://localhost:8888”来源