MEAN堆栈文件上传

Posted

技术标签:

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

我正在开发一个 MEAN 堆栈 Web 应用程序,我想使用 ng2-file-upload 上传文件。 这是我的 Angular 2 代码。

clas-s-room.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 />

clas-s-room.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 属性控制。

这是什么原因?

【问题讨论】:

【参考方案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】:

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

    Angular 2 应用,端口号为 4200 端口号为 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();
);

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

    首先使用“ng build”构建 Angular 应用程序以直接部署在 MEAN 堆栈应用程序下。 这将在 Angular 应用程序中生成“dist”文件夹。

    将此 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”来源

【讨论】:

以上是关于MEAN堆栈文件上传的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 mean.js 上传图像并将其保存到数据库(猫鼬)

从客户端或服务器上传到 S3?

Heroku 应用程序的免费层是不是支持文件上传?

如何将 MEAN 堆栈部署到我的托管服务器?

我如何在 Digital Ocean 上上传我的 MEAN 应用程序(网站应用程序)?

使用具有角度7平均堆栈的multer中间件上传文件不起作用