从Node.js获取函数进度并在客户端上输出它

huangapple go评论69阅读模式
英文:

Get function progress from nodejs and output it on client side

问题

// Progress Tracking
ffmpeg.stderr.on('data', (data) => {
  if (timeMatch) {
    progress = Math.floor((currentTime / duration) * 100);
    console.log(`FFmpeg in progress : ${progress}%`);
    res.write(`data: ${progress}\n\n`);
  }
});


// Send the output file as a response once the process is complete
ffmpeg.on("close", () => {
  fs.readFile(outputPath, (err, data) => {
    async function uploadData() {
      const result = await bucket.upload(outputPath);
      if (result) {
        res.json({ mediaLink: `https://firebasestorage.googleapis.com/${fileName}?alt=media&token=${idtoken}` });
      } else {
        res.status(500).send('Error: could not get media link');
      }
    }
    uploadData();
  });
});

On react client side I am trying with this but not sure if that's correct

.then(response => {
  const data = response.data;
  if (data.progress) {
    console.log('Progress:', data.progress);
    // Update UI or perform actions with the progress value
  }
  if (data.mediaLink) {
    console.log('Final data:', data.mediaLink);
    // Perform actions with the final data
  }
})

The error I get on nodejs server is

ERR_HTTP_HEADERS_SENT

Error on the client side

net::ERR_INCOMPLETE_CHUNKED_ENCODING 200 (OK)
英文:

I have the code below that runs ffmpeg command my goal is to get the progress that shows correctly on server logs but the issue is I cannot figure out the logic to send progress and then end the connection after completing the additional code

// Progress Tracking
ffmpeg.stderr.on('data', (data) => {
  if (timeMatch) {
    progress = Math.floor((currentTime / duration) * 100);
    console.log(`FFmpeg in progress : ${progress}%`);
    res.write(`data: ${progress}\n\n`);
  }
});


// Send the output file as a response once the process is complete
ffmpeg.on("close", () => {
  fs.readFile(outputPath, (err, data) => {
    async function uploadData() {
      const result = await bucket.upload(outputPath);
      if (result) {
        res.json({ mediaLink: `https://firebasestorage.googleapis.com/${fileName}?alt=media&token=${idtoken}` });
      } else {
        res.status(500).send('Error: could not get media link');
      }
    }
    uploadData();
  });
});

On react client side I am trying with this but not sure if that's correct

.then(response => {
  const data = response.data;
  if (data.progress) {
    console.log('Progress:', data.progress);
    // Update UI or perform actions with the progress value
  }
  if (data.mediaLink) {
    console.log('Final data:', data.mediaLink);
    // Perform actions with the final data
  }
})

The error I get on nodejs server is

> ERR_HTTP_HEADERS_SENT

Error on client side

> net::ERR_INCOMPLETE_CHUNKED_ENCODING 200 (OK)

答案1

得分: 1

问题在于,你试图使用纯粹的HTTP 方法来做这件事是不可能的。

在你能够发送HTTP响应的正文之前,你必须发送头部。一旦发送了头部,就不能返回或发送新的头部。这是一个单向操作。如果你尝试多次发送头部,node.js 会抛出错误 ERR_HTTP_HEADERS_SENT。这就是你遇到的错误。

第一次调用 res.write() 时,如果尚未发送头部,它将发送一些默认的头部。但是,res.json() 需要每次调用时都发送头部,因为它需要告诉客户端它在头部中发送的是JSON。因此,由于你只能发送头部一次,你可以要么只调用一次 res.json(),要么调用 res.write() 多次,但不能同时使用两者。

如果你想实时向客户端传递关于 ffmpeg 进度的实时更新,我建议你考虑使用像 WebSocket 这样的其他方法,它允许你实现这个目标。

英文:

The issue is that the way you are trying to do this is not possible with plain old HTTP.

Before you can send the body of an HTTP response, you must send the headers. After you send the headers, you can't go back or send new headers. It's a one-way thing. If you try to send headers multiple times, node.js will give throw the error ERR_HTTP_HEADERS_SENT. This is the error you're getting.

The first time res.write() is called, it will send some default headers if headers haven't already been sent. However, res.json() needs to send headers every time it is called because it needs to tell the client that it is sending JSON in the headers. So because you can only send headers once, you can either call res.json() once, or res.write() as much as you need. Not both.

If you want to stream realtime updates to the client about the progress of ffmpeg, then I suggest looking into something else like web sockets which allow you to do this.

huangapple
  • 本文由 发表于 2023年5月28日 03:37:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/76348721.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定