如何加速node.js文件操作?

Dam*_*ran 1 performance download mongoose node.js express

在我的项目中,客户端将请求从具有id的服务器下载文件.我必须执行以下操作:

  • 验证mongoDb中的id
  • 检查扩展名
  • 检查文件是否存在
  • 读取文件并将内容写入响应

我使用以下代码检查文件并发送响应.

fs.exists(filename, function(exists) {
  if (!exists) {
    res.writeHead(404, '', {
      "Content-Type" : "text/plain"
    })
    res.write("404 Not Found\n");
    res.end();
    return;
  }
  fs.readFile(filename, "binary", function(err, file) {
    if (err) {
      res.writeHead(500, '', {
        "Content-Type" : "text/plain"
      })
      res.write(err + "\n");
      res.end();
      return;
    }
    res.setHeader("Pragma", "public");
    res.setHeader("Cache-Control: private, max-age=3600");
    res.setHeader("Transfer-Encoding:  chunked");
    res.setHeader("Range:  chunked");
    res.writeHead(200, '', {
      "Content-Type" : contentType
    });
    res.write(file, "binary");
    res.end(file, "binary");
  });
});
Run Code Online (Sandbox Code Playgroud)

在几毫秒内,客户端将请求数百个文件.支持的文件类型是图像,音频或视频.

当文件夹中有大量文件时,node.js花费了太多时间来下载文件.如何提高性能?

log*_*yth 5

我会推荐一些东西.

  1. 你不应该使用'binary'.根本不要给出编码.通过添加编码,您正在使节点执行大量额外工作以将文件的Buffer对象转换为二进制编码string.write再次调用时'binary',表示节点必须反向执行相同的操作.另外你在文件传递给双方endwrite,这意味着每次下载将包含文件数据两次文件.

  2. 我建议不要使用readFile.由于readFilefile变量中将整个文件内容传递给您,因此您需要节点将文件的全部内容加载到RAM中,这意味着它需要分配大量缓冲区然后将它们连接起来,这是不必要的工作.

  3. 没有理由exists单独使用,因为如果您尝试打开不存在的文件,错误将告诉您,因此首先检查只是额外的工作.

此外,Transfer-encoding标题将自行设置,您不需要这样做.

这样的事情应该更快:

fs.createReadStream(filename)
    .on('error', function(err){
        if (err.code === 'ENOENT'){
            res.writeHead(404, {
                'Content-type': 'text/plain'
            });
            res.end('404 Not Found\n');
        } else {
            res.writeHead(500, {
                'Content-type': 'text/plain'
            });
            res.end(err + '\n');
        }
    })
    .on('open', function(){
        res.writeHead(200, {
            'Pragma': 'public',
            'Cache-Control': 'private, max-age=3600',
            'Content-type': contentType
        });
    })
    .pipe(res);
Run Code Online (Sandbox Code Playgroud)