【问题标题】:MEAN stack file uploadMEAN堆栈文件上传
【发布时间】:2017-09-20 04:42:52
【问题描述】:

我正在开发一个 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。回应 预检请求未通过访问控制检查: 响应中的“Access-Control-Allow-Origin”标头不能是 当请求的凭据模式为“包含”时,通配符“*”。起源 'http://localhost:4200' 因此不允许访问。这 XMLHttpRequest 发起的请求的凭证模式是 由 withCredentials 属性控制。

这是什么原因?

【问题讨论】:

    标签: javascript node.js angular mean-stack


    【解决方案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 支持 *、null 或确切的协议 + 域 + 端口 -> http://www.w3.org/TR/cors/#access-control-allow-origin-response-header

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

    【讨论】:

      【解决方案2】:

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

      1. Angular 2 应用,端口号为 4200
      2. 端口号为 3000 的 MEAN 堆栈应用程序

      因此,当 Angular 2 应用程序尝试对端口号为“3000”的 MEAN 堆栈应用程序进行任何调用时,浏览器会报错,因为它将被视为跨域 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. 首先使用“ng build”构建 Angular 应用程序以直接部署在 MEAN 堆栈应用程序下。
      2. 这将在 Angular 应用程序中生成“dist”文件夹。
      3. 将此 dist 文件夹移动到 MEAN stack app 的根文件夹下并添加以下代码行

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

      通过执行上述步骤,我们仅运行 MEAN 堆栈下的一个应用程序,前端将从 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: * doesn't match localhost。鉴于您已按照其他答案的建议为您的 OPTIONS 请求设置了正确的 CORS 标头,您的预检请求将返回 正确 标头,但 chrome 不会将 localhost 确认为有效域匹配*,并且将无法通过预检。

            要解决此问题,一个快速的解决方案是在您的主机文件中添加一个假域,例如 local.development,然后指向该域而不是 localhost。您的跨域请求现在应该可以工作了。

            【讨论】:

              【解决方案6】:

              本地主机快速修复:

              使用 Allow-Control-Allow-Origin Chrome 扩展,然后使用 * 在列表中添加 localhost

              希望这会有所帮助。

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

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

              【讨论】:

                【解决方案7】:

                也许这会有所帮助:

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

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

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2021-02-25
                  • 1970-01-01
                  • 2015-11-16
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多