【问题标题】:Node.js connection reset on file upload with multer使用 multer 在文件上传时重置 Node.js 连接
【发布时间】:2021-01-19 14:41:01
【问题描述】:

我有一个使用 multer 处理文件上传的 node/express 应用程序。在我的本地机器上一切正常,但在服务器上,如果上传的文件超过几 Mbs,浏览器会因“连接重置”错误而停止。

这里是上传脚本的简单测试版:

var express = require('express');
var multer = require('multer');

// Create server
var app = express();

// Start server
function startServer() {
    var port = 8888;
    server = app.listen(port, function () {
        console.log('Node version:' + process.versions.node);
        console.log('Express server listening on port %d in %s mode', port, app.settings.env);
    });
}

var upload = multer({dest: './tmp/'});

var app = express()

app.post('/', upload.single('data'), function (req, res, next) {
    console.log(req.file);
});

startServer();

这是测试上传的 html 页面:

<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="x-ua-compatible" content="ie=edge">
        <title>Test Upload</title>
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">

    </head>
    <body>
        <p>Hello world! This is a test upload.</p>

        <form method="post" action="http://192.168.1.234:8888" enctype="multipart/form-data">
            <label>file</label><br>
            <input type="file" name="data"><br>

            <input type="submit" name="submit" value="Upload">
        </form>


    </body>
</html>

我在两台不同的服务器上进行了测试——一台 VPS 和一台裸机——我最终在两台服务器上都遇到了同样的错误。上传开始,我可以在我的./tmp 目录中看到一个文件块,但它永远不会完成并且不会抛出任何错误,无论是在节点中还是在系统日志中。

【问题讨论】:

  • 根据我的经验,这可能是 apache / nginx / 其他服务器正在运行的超时配置,我会尝试调查。
  • 可能没有足够的磁盘空间?
  • @NadavL 到目前为止节点是前端服务器,没有任何代理...
  • @MedetTleukabiluly 在一台服务器上还有几台 Gig,而另一台则有几百台,所以我认为这不是问题的根源。

标签: javascript node.js file-upload multer


【解决方案1】:

@NadavL 是对的,尽管我没有前端服务器,但节点本身正在超时。

the docs 中写到 node 默认没有超时。 Express 可能会覆盖它,但我找不到有关此事的任何信息。

要全局定义特定的超时,您可以通过更改服务器连接时的套接字超时来继续

[…]

// Start server
function startServer() {
    var port = 8888;
    server = app.listen(port, function () {
        console.log('Node version:' + process.versions.node);
        console.log('Express server listening on port %d in %s mode', port, app.settings.env);
    });

    server.on('connection', function(socket) {
        // 10 minutes timeout
        socket.setTimeout(10 * 60 * 1000);
    });
}

但是由于高超时会使您的服务器暴露于Slow HTTP Attacks,您可能希望仅针对特定路由更改默认超时 - 在我的情况下,仅针对上传路由。在这种特殊情况下,您所要做的就是更改路由处理程序中的超时时间,如下所示:

app.post('/myroute', function (req, res) {
    // 10 minutes timeout just for POST to myroute
    req.socket.setTimeout(10 * 60 * 1000);
    upload.single('data');
    console.log(req.file);
});

还有一个专门的中间件来处理超时,它被称为connect-timeout,它也可以用来为不同的路由配置特定的超时(参见this post on SO)。

【讨论】:

    【解决方案2】:

    据我了解我的问题,在上传大文件 60 秒后收到 ERR_CONNECTION_RESET。用req.setTimeout(value, cb) 增加请求超时是不够的。

    服务器headersTimeout字段需要手动增加:

    server.headersTimeout = timeoutValue;
    

    Node Doc on server_headers_timeout

    Github issue describing the solution in details

    【讨论】:

    • 我花了超过 8 个小时来解决这个问题,但这个答案又为我保存了几十个小时。谢谢。
    猜你喜欢
    • 2017-12-03
    • 2016-05-22
    • 2016-03-06
    • 2020-12-27
    • 2020-09-27
    • 1970-01-01
    • 2019-06-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多