节点.js连接在使用 multer 上传文件时重置

Node.js connection reset on file upload with multer

本文关键字:文件 multer 连接 js 节点      更新时间:2023-09-26

我有一个节点/快递应用程序,它使用 multer 处理文件上传。在我的本地计算机上一切正常,但是在服务器上,如果上传的文件超过几个 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 目录中看到该文件的大量内容,但它从未完成并且不会在节点和系统日志中抛出任何错误。

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

文档中写着默认情况下节点中没有超时。快递可能会覆盖它,但我找不到有关此事的任何信息。

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

[…]
// 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);
    });
}

但是,由于高超时会增加服务器遭受慢速 HTTP 攻击的风险,您可能希望仅更改特定路由的默认超时 - 在我的情况下,仅针对上传路由。在这种特殊情况下,您所要做的就是更改路由处理程序中的超时,如下所示:

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);
});

还有一个专用的中间件来处理超时,它被称为连接超时,它也可以用来为不同的路由配置特定的超时(参见SO上的这篇文章)。

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

服务器headersTimeout字段需要手动增加,如下所示:

server.headersTimeout = timeoutValue;

server_headers_timeout上的节点文档

详细描述解决方案的 Github 问题