0

I have an endpoint that is supposed to make a call to the WhatsApp API with the Media URL just like they said to do here: https://developers.facebook.com/docs/whatsapp/cloud-api/reference/media#download-media, and just return it the same way it was returned from whatsapp as well as save the file for later use.

   exports.downLoadMedia = async (req, res) => {
  const url = req.query.url;

  request.get(
    {
      url: url,
      headers: {
        Authorization: `Bearer ${process.env.AUTH_TOKEN}`,
        Accept: 'audio/ogg',
      },
      encoding: null, // Set encoding to null to receive binary data
    },
    function (err, resp, body) {
      if (err) {
        console.log("Error:", err);
        res.status(500).json({ error: "An error occurred." });
      } else {
          const fileName = 'downloaded_audio.ogg';
          const filePath = path.join(__dirname, fileName); // Construct file path

          fs.writeFile(filePath, body, 'binary', (writeErr) => {
            if (writeErr) {
              console.log("Error writing file:", writeErr);
              res.status(500).json({ error: "An error occurred while saving the audio." });
            } else {
              // Use res.download() to send the saved file as a download response
              res.download(filePath, 'downloaded_audio.ogg', (downloadErr) => {
                if (downloadErr) {
                  console.log("Error sending download:", downloadErr);
                  res.status(500).json({ error: "An error occurred while sending the download." });
                }
              });
            }
          });
      }
    }
  );
};

when i make a get request in Postman with the WhatsApp Media url directly it shows up like this:

enter image description here

and the audio plays as it should.

However, when i make a request to my endpoint above it shows up like this:

enter image description here

The audio is saved but it does not play.

Basically, my endpoint should be the proxy to get the audio/voice note file.

Davia
  • 73
  • 10

2 Answers2

0

EDIT: The user agent was the issue. After using "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36", it worked.

Same issue. I'm actually receiving HTML which is pasted in the .ogg file with the following content https://goonlinetools.com/html-viewer/#ltk64rzrvcjrm18bvbae

when using postman, everything works fine - really struggling what's actually wrong. Headers are all the same

Working example:

const config = {
    headers: {
      "Authorization": `Bearer ${whatsapp_token}`,
      "User-Agent":
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36",
      // "NONISV|MyBot|MyBot/12.0",
    },
    responseType: "arraybuffer",
    };

    const response = await axios
    .get(media_info.url, config)
    .then(
      (media_file) => Buffer.from(media_file.data)
    )
    .then((buffer) =>
      // do something with the buffer
   );
Max
  • 11
  • 2
  • Hello, could you please share the code how it should look like. – Endery Aug 25 '23 at 06:52
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Aug 25 '23 at 06:52
0

Got it to work after switching from using the request package to axios to handle the call to whatsapp api, then setting a couple more headers for the response.

Also setting the response type as a stream, then piping the response using axios.

The file is not saved; however, the response is the file itself, just like when i make the call to the url directly in postman, where i can download the file and it is easier to work with.

exports.downLoadMedia = async (req, res) => {  

const url = req.query.url;

  try {
    // Fetch the audio data from the external URL with the auth token
    const audioResponse = await axios.get(url, {
      responseType: 'stream',
      headers: {
        Authorization: `Bearer ${process.env.META_AUTH_TOKEN}`,
      }
    });

    // Set appropriate headers for streaming audio
    let fileName = Date.now().toString() + "_audio.ogg";
    res.setHeader('Content-Type', 'audio/ogg');
    res.setHeader('Content-Disposition', `attachment; filename=${fileName}`);
    res.setHeader('Transfer-Encoding', 'chunked');

    // Pipe the audio stream from the external response to the current response
    audioResponse.data.pipe(res);
  } catch (error) {
    res.status(500).send('Error fetching audio data: ' + error.message);
  }
};
Davia
  • 73
  • 10