【问题标题】:NodeJS/Express can't set headers after they are sent error when I upload files当我上传文件时,NodeJS/Express 在发送错误后无法设置标题
【发布时间】:2014-05-28 20:50:54
【问题描述】:

我正在开发一个小型门户网站,当我上传文件(图像)> ~25kb 时遇到了错误。我已经测试过这个系统,它适用于小图像,但是当我尝试使用更大的图像时,一切都中断了。

我正在使用最新版本的节点,表达 3.4.0,multer 0.0.7,这里是有问题的代码:

服务器:

var express = require('express'),
    multer = require('multer'),
    api = require('./routes/api.js'),
    http = require('http'),
    path = require('path'),
    app = express(),
    server = http.createServer(app);


app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
app.set('port', process.env.VCAP_APP_PORT || 7000);
app.use(multer({dest: __dirname + '/uploads/'}))
app.use(app.router);

app.configure(function()
    app.use("/uploads",express.static(__dirname + '/uploads'));

    app.post('/api/upload/file', api.upload);

    app.use(function(err, req, res, next) {
        if(!err) return next();
        console.log(err.stack);
        res.json({error: true});
    });

    app.use(multer({
        dest:'./uploads/',
         rename: function (fieldname, filename) {
            return filename.replace(/\W+/g, '-').toLowerCase();
        }
    }));
});

server.listen(app.get('port'), function(){
    console.log('Express server listening on port ' + app.get('port'));
});

还有api.upload函数:

exports.upload = function(req, res) {

    console.log("Upload");
    var resumeName = null,
        picName = null;
    console.log("File: " + JSON.stringify(req.files));
    if(req.files.resume.size >= 0 || req.files.pic.size >= 0) {
        if(req.files.resume.size > 0) {
            resumeName = req.files.resume.name;
        }
        if(req.files.pic.size > 0) {
            picName = req.files.pic.name;
        }
        console.log("Got file");
    }
    console.log("sending...");
    res.send({picName: picName, resumeName: resumeName});
}

如果有帮助的话,我的前端是有角度的,我正在使用 restangular 和 ng-upload 来协助提交和上传文件。

【问题讨论】:

    标签: node.js file-upload express mean-stack


    【解决方案1】:

    您正在app.configure() 中配置您的应用程序

    app.configure(function()
        app.use("/uploads",express.static(__dirname + '/uploads'));
    
        app.post('/api/upload/file', api.upload);
    
        app.use(function(err, req, res, next) {
            if(!err) return next();
            console.log(err.stack);
            res.json({error: true});
        });
    
        app.use(multer({
            dest:'./uploads/',
             rename: function (fieldname, filename) {
                return filename.replace(/\W+/g, '-').toLowerCase();
            }
        }));
    });
    

    在它之外。

    app.use(express.logger('dev'));
    app.use(express.json());
    app.use(express.urlencoded());
    app.set('port', process.env.VCAP_APP_PORT || 7000);
    app.use(multer({dest: __dirname + '/uploads/'}))
    app.use(app.router);
    

    请注意,您已经定义了两次 multer 中间件。

    我猜 multer 必须在 app.use(app.router) 之前定义。第二个定义是在发送标头后导致发送标头。

    注意: app.configure() 已被弃用,甚至从 express 4.x 开始已被删除。我不推荐它的用法。您最好在外面定义所有中间件。

    【讨论】:

    • 我继续更新到 express 4.0,删除了 app.configure() 和 app.use(multer({dest: __dirname + '/uploads/'}))。我的代码仍然适用于小图像,但仍然会在较大的图像上崩溃。也许这是multer的问题?在此期间,我将进行更多测试。
    • 这很奇怪。这似乎是multer的问题。试试github.com/mscdex/connect-busboygithub.com/andrewrk/connect-multiparty
    【解决方案2】:

    TL;DR 在将上传内容保存在服务器上时存在(相当于)一个竞争案例。单独上传文件解决了这个问题。

    我最终听从了@Leonel 的建议,转而使用 connect-busboy。最初我有同样的问题,然后我意识到发生了什么。我在前端使用 ng-upload,但是 ng-upload 会一次性上传所有文件。由于我使用的表单有两个(可选)用户可以上传的文件,后端上传服务将被 req.files 中的两个文件击中。由于我对 multer 的实现并没有很好地计划这一点,它会尝试同时处理这两种情况,但只会发送一个响应(它首先击中 res.send 行)。

    为了解决这个问题,我搬到了angular-file-upload,这让我可以在上传文件的方式上拥有更多选择(将单独上传)。另外,我使用safwanc's solution来使用connect-busboy进行文件上传。

    【讨论】:

      猜你喜欢
      • 2018-09-25
      • 2017-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-22
      相关资源
      最近更新 更多