【问题标题】:Express app.post getting called multiple timesExpress app.post 被多次调用
【发布时间】:2016-04-08 20:53:57
【问题描述】:

我一直在构建一个 youtube 视频转换应用程序,它使用 youtube-dl 流式传输 youtube 视频并保存它们,一切正常,直到我尝试流式传输一个超过一个小时的视频。当任务完成 50% - 100% 或 40-80 秒时,整个代码块将重新运行,从而导致同时发生多个流。因此,响应在等待管道完成时永远不会被发送。添加下一个();在流函数之外允许转换完成而不会中断或重新运行代码块,但是在尝试发送响应时会导致以下错误:

throw new Error('Can\'t set headers after they are sent.');

这是有问题的 Node.js 代码块:

app.post('/convert/', function (req, res, next){
  var url = 'http://www.youtube.com/'+req.body.url;
  var quality = req.body.quality;
  var socketId = req.body.socketId;


stream = youtubedl(url, 
  ['-f ' + quality],

  // // Additional options can be given for calling `child_process.execFile()`. 
  { cwd: __dirname });

stream.on('info', function(info) {

  console.log('Download started');
  console.log('filename: ' + info._filename);
  console.log('size: ' + info.size);
  console.log('format: ' + info.format);

  var fileName = info._filename;
  var videoId = info.id;
  var videoTitle = info.title;
  videoTitle = videoTitle.replace(/[^a-zA-Z0-9\s]/g, '');
  console.log(videoTitle);

  var mp4 = 'downloads/'+videoTitle+'-'+info.format_id+'.mp4';
  fs.writeFile(mp4, "file", function(err) {
      if(err) {
          return console.log(err);
      }

    console.log("The file was saved!");
    var stat = fs.statSync(mp4);
    var str = progress({
      length: info.size,
      time: 100
    });

    str.on('progress', function(progress) {
      io.to(global.socketid).emit('progressVideo',{progress: progress.percentage});
      console.log(info.size);
      console.log(progress.transferred);
      console.log(progress.percentage);
      console.log(progress.remaining);
    });

    var pipe = stream.pipe(str).pipe(fs.createWriteStream(mp4));

    pipe.on('finish', function () {
      console.log("stream finished.");
      res.json(videoTitle+'-'+info.format_id+'.mp4');
    });
  });
 });
 // next();
});

由一些 Angular 代码调用。

// Sends youtube link to backend
$scope.getVideo = function(youtubeLink, resolution){
    var cleanedLink = youtubeLink.substring(24);
    var url = {url: cleanedLink, quality: resolution};
    $http.post('/convert/', url).success(function (response){
      // Do some stuff
    });
}

对为什么它运行不止一次感到困惑,我慢慢地删除了越来越多的代码,直到剩下这个简单的测试。

app.post('/convert/', function (req, res, next){
  console.log('hello!');
});

由 ng-click 事件调用,等待一分钟左右后,控制台还打印出两个和三个 hello! 语句。我完全不知道为什么会这样。如果有人能为我阐明这一点,将不胜感激。

【问题讨论】:

    标签: javascript angularjs node.js express youtube-dl


    【解决方案1】:

    因此,在进入一个非常基本的发布路线并注销一些文本但没有返回响应之后,我得出的结论是问题出在 node.js 上。我决定记录 console.log 语句之间的时间长度,结果是每 2 分钟一次。有了这个,我可以发现如果没有将响应发送回客户端,该节点的默认超时时间为 2 分钟。

    我可以使用以下代码将响应设置为永不超时:

    res.connection.setTimeout(0);

    我希望这对需要长时间保持连接以进行文件转换/传输等的其他人有所帮助...

    【讨论】:

    • 此解决方案适用于本地,但不适用于 aws 服务器。我也增加了nginx的时间,但仍然抛出错误
    猜你喜欢
    • 2018-08-04
    • 1970-01-01
    • 1970-01-01
    • 2016-10-18
    • 1970-01-01
    • 1970-01-01
    • 2020-06-08
    • 2010-10-24
    相关资源
    最近更新 更多