我使用fs.createReadStream(path).pipe(res);
使用Express流式传输HTML 5视频,如果我刷新页面太多次(成千上万次),最终会导致错误Error: EMFILE: too many open files
。我假设我需要执行某种清理并关闭文件以防止这种情况,但我不确定需要做什么。
每次用户寻找客户端未加载的视频的一部分时,我都会创建一个读取流,这会在几分钟内发生此问题。任务管理器显示相同的文件打开数百次,因此似乎永远不会关闭。
流功能的相关部分:
fs.stat(path, function(err, stats) {
var size = stats.size;
var range = req.headers.range;
if (range) {
var parts = range.replace(/bytes=/, '').split('-');
var start = parseInt(parts[0]);
var end = parts[1] ? parseInt(parts[1]) : size - 1;
var chunksize = (end - start) + 1;
res.writeHead(206, {
'Content-Range': 'bytes ' + start + '-' + end + '/' + size,
'Accept-Ranges': 'bytes',
'Content-Length': chunksize,
'Content-Type': 'video/mp4'
});
fs.createReadStream(path, {start: start, end: end}).pipe(res);
} else {
res.writeHead(200, {
'Content-Length': size,
'Accept-Ranges': 'bytes',
'Content-Type': 'video/mp4'
});
fs.createReadStream(path).pipe(res);
}
});
答案 0 :(得分:1)
事实证明,流只会被破坏而文件在到达结束时关闭 - 这很少发生,因为你必须加载整个文件而不寻求或关闭浏览器。
要解决此问题,您必须侦听响应的close事件并销毁该流:
res.on('close', function() {
stream.destroy();
});
有时,即使将close函数放在请求函数的第一行,也永远不会调用它。我发现解决这个问题的一个相当hacky的方法是在创建流之前检查套接字是否被销毁:
if (req.socket.destroyed) {
return;
}
固定流功能:
fs.stat(path, function(err, stats) {
if (req.socket.destroyed) {
return;
}
var stream;
var size = stats.size;
var range = req.headers.range;
if (range) {
var parts = range.replace(/bytes=/, '').split('-');
var start = parseInt(parts[0]);
var end = parts[1] ? parseInt(parts[1]) : size - 1;
var chunksize = (end - start) + 1;
res.writeHead(206, {
'Content-Range': 'bytes ' + start + '-' + end + '/' + size,
'Accept-Ranges': 'bytes',
'Content-Length': chunksize,
'Content-Type': 'video/mp4'
});
stream = fs.createReadStream(path, {start: start, end: end});
} else {
res.writeHead(200, {
'Content-Length': size,
'Accept-Ranges': 'bytes',
'Content-Type': 'video/mp4'
});
stream = fs.createReadStream(path);
}
stream.pipe(res);
res.on('close', function() {
stream.destroy();
});
});
答案 1 :(得分:0)
在Linux / Unix上EMFILE
问题由ulimit
解决。
我不确定在窗户上。
Google Windows ulimit EMFILE
获得此Stack Overflow
https://stackoverflow.com/a/729204/683017
它说每个进程的2048个文件描述符是Windows的限制。这符合你的说法
“成千上万”
如果这个2048是一个坚定的限制,我不确定,(你将不得不四处寻找有关你的特定操作系统的更多信息)。
如果可能的话,可以考虑将负载重新平衡到更多进程或更多服务器。