节点请求处理程序以流重新启动

Node request handler restarting with stream

很抱歉提出这种具体问题,但我遇到了一个非常奇怪的问题,我不确定为什么会这样。

我正在编写一个 Node 应用程序,它采用 Youtube videoID,然后将音频流式传输给请求者。这是代码。

router.get('/video/:videoId', function(req, res, next) {
  console.log('requested ' + req.params.videoId);
  var filename = req.params.videoId + ".mp3";

  youtubeDL.exec(req.params.videoId, ['-x', '--audio-format', 'mp3', '-o', filename], {}, function(err, output) {
    if (err){
      res.send("bad request");
      return;
    }else{
      console.log("exec begin")
      res.setHeader("content-type", "audio/mp3");
      fs.createReadStream(filename).pipe(res);
      fs.unlink(filename);
      console.log("exec end")
    }
  });
  console.log("router end");
});

问题是请求开始了 "looping" 我想我会这样描述它,请求在停止前被调用了 3 次。

例如,这是 http://localhost:3000/resources/video/JCHTX_pgw6A

的输出
requested JCHTX_pgw6A
router end
[Long pause here]
exec begin
exec end
GET /resources/video/JCHTX_pgw6A 200 17396.280 ms - -
requested JCHTX_pgw6A
router end
[Long pause here]
exec begin
exec end
GET /resources/video/JCHTX_pgw6A 200 17550.309 ms - -
requested JCHTX_pgw6A
router end
[Long pause here]
exec begin
exec end
GET /resources/video/JCHTX_pgw6A 200 1645.932 ms - -

它停止的地方。有没有人知道为什么会发生这种情况或如何获取更多信息?我完全被难住了。

您不应在 开始 后立即调用 fs.unlink() 以流式传输文件,否则文件将停止流式传输到客户端。相反,要么找到一种直接从 youtube 流式传输的方法(恕我直言,这是一种更好的解决方案,因为您可以避免碰到磁盘) 至少等到文件完成流式传输后再删除它。对于后者,可能看起来像:

console.log("exec begin")
res.setHeader("content-type", "audio/mp3");
fs.createReadStream(filename).pipe(res).on('finish', function() {
  fs.unlink(filename);
});
console.log("exec end")

或者甚至更好(等待文件描述符首先实际关闭):

console.log("exec begin")
res.setHeader("content-type", "audio/mp3");
fs.createReadStream(filename).on('close', function() {
  fs.unlink(filename);
}).pipe(res);
console.log("exec end")

将请求方法更改为 POST,它停止了错误行为。