问题
I have a node/express app that handles file uploads with multer. Everything works well on my local machine, but on the server, if the uploaded file exceeds a couple of Mbs, the browser stops with a "connection reset" error.
Here is a simple test version of the upload script:
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();
And here's the html page to test the upload:
<!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>
I tested on two different servers – a VPS and a bare-metal box – I ended up with the same error on both servers. The upload starts and I can see a chunck of the file in my ./tmp
directory, but it never finishes and doesn't throw any error, neither in node nor in the syslog.
回答1:
@NadavL was right, despite the fact that I had no front server, node was timing out itself.
It's written in the docs that there's no timeout in node by default. Express might override that but I couldn't find any information on the matter.
To define a specific timeout globally, you can proceed by changing the socket timeout when the server connects
[…]
// 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);
});
}
But as a high timeout rises your server's exposure to Slow HTTP Attacks, you might want to change the default timeout just for a specific route – in my case, just for the upload route. In this particular case, all you have to do is change the timeout in your route's handler like so:
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);
});
There's also a dedicated middleware to handle timeouts, it's called connect-timeout and it can be used to configure specific timeouts for different routes too (see this post on SO).
回答2:
As far as I understood my issue, receiving ERR_CONNECTION_RESET after 60 seconds uploading big files. Increasing the request timeout with req.setTimeout(value, cb)
isn't enough.
The server headersTimeout
field needs to be increased manually as such:
server.headersTimeout = timeoutValue;
Node Doc on server_headers_timeout
Github issue describing the solution in details
来源:https://stackoverflow.com/questions/34892240/node-js-connection-reset-on-file-upload-with-multer