WhatsApp API语音消息下载代理端点异常:音频无法播放问题
排查WhatsApp Cloud API媒体代理端点音频无法播放的问题
问题分析
直接请求WhatsApp媒体URL能正常播放音频,但通过代理端点获取并保存的音频无法播放,核心问题大概率出在二进制数据处理、请求重定向处理或响应头传递环节,以下是具体排查和修复方案:
可能的问题点及修复步骤
1. 未跟随重定向
WhatsApp的媒体URL可能返回302跳转,默认request库可能不自动跟随重定向,导致获取的不是实际音频数据。
- 修复:在请求配置中添加重定向跟随设置
request.get( { url: url, headers: { Authorization: `Bearer ${process.env.AUTH_TOKEN}`, Accept: 'audio/ogg', }, encoding: null, followRedirect: true, // 开启自动跟随重定向 maxRedirects: 5, // 设置最大重定向次数 }, // 后续回调逻辑 );
2. 二进制文件写入编码错误
代码中写入文件时指定了'binary'编码,但encoding: null已将响应转为Buffer,额外指定编码会导致数据损坏。
- 修复:移除写入文件时的编码参数
// 原代码 fs.writeFile(filePath, body, 'binary', (writeErr) => { ... }) // 修改后 fs.writeFile(filePath, body, (writeErr) => { ... })
3. 重复读写文件引入的风险
先写入本地再通过res.download读取返回,多了一次IO操作,可能引入文件读取错误。可以直接将获取到的Buffer返回给客户端,同时保存文件。
- 修复:替换
res.download为直接发送Buffer,并传递正确的响应头
// 替换res.download逻辑 res.setHeader('Content-Type', resp.headers['content-type'] || 'audio/ogg'); res.setHeader('Content-Disposition', `attachment; filename="downloaded_audio.ogg"`); res.send(body);
4. 缺少参数校验与错误状态码处理
原代码未校验url参数是否存在,也未处理WhatsApp返回的非200状态码,容易隐藏问题。
- 修复:添加参数校验和状态码判断
exports.downLoadMedia = (req, res) => { const url = req.query.url; if (!url) { return res.status(400).json({ error: "Missing media URL parameter" }); } request.get(/* ... */, function (err, resp, body) { if (err) { console.error("Request error:", err); return res.status(500).json({ error: "Failed to fetch media" }); } // 检查WhatsApp返回的状态码 if (resp.statusCode !== 200) { console.error("Media fetch failed with status:", resp.statusCode, resp.body.toString()); return res.status(resp.statusCode).json({ error: "Failed to fetch media from WhatsApp" }); } // 后续文件保存和响应逻辑 }); };
完整修复后的代码
const request = require('request'); const path = require('path'); const fs = require('fs'); exports.downLoadMedia = (req, res) => { const url = req.query.url; if (!url) { return res.status(400).json({ error: "Missing media URL parameter" }); } request.get( { url: url, headers: { Authorization: `Bearer ${process.env.AUTH_TOKEN}`, Accept: 'audio/ogg', }, encoding: null, followRedirect: true, maxRedirects: 5, }, function (err, resp, body) { if (err) { console.error("Request error:", err); return res.status(500).json({ error: "Failed to fetch media" }); } if (resp.statusCode !== 200) { console.error("Media fetch failed with status:", resp.statusCode, resp.body.toString()); return res.status(resp.statusCode).json({ error: "Failed to fetch media from WhatsApp" }); } const fileName = 'downloaded_audio.ogg'; const filePath = path.join(__dirname, fileName); fs.writeFile(filePath, body, (writeErr) => { if (writeErr) { console.error("File write error:", writeErr); // 即使保存失败,优先返回音频给客户端 res.setHeader('Content-Type', resp.headers['content-type'] || 'audio/ogg'); res.setHeader('Content-Disposition', `attachment; filename="downloaded_audio.ogg"`); return res.send(body); } // 直接返回原始Buffer res.setHeader('Content-Type', resp.headers['content-type'] || 'audio/ogg'); res.setHeader('Content-Disposition', `attachment; filename="downloaded_audio.ogg"`); res.send(body); }); } ); };
额外排查建议
- 对比直接请求和代理返回的文件大小,若不一致说明数据传输过程中损坏
- 使用
ffmpeg -i downloaded_audio.ogg检查文件是否为有效OGG格式,报错则说明文件已损坏 - 查看控制台日志,确认是否有请求错误或非200状态码返回
内容的提问来源于stack exchange,提问作者Davia
相关产品推荐
相关产品推荐

