如何正确将音频blob从React前端传递到Express后端
问题原因&解决方案
1. 前端代码错误修正
你当前的写法是把FormData实例套在了普通对象里作为payload,axios不会自动解析这个对象里的FormData,反而会尝试把整个payload序列化为JSON,导致后端接收到的格式完全错误。同时手动指定multipart/form-data请求头会丢失必要的边界(boundary)参数,导致格式解析失败,axios会自动补全该请求头无需手动设置。
直接把FormData实例作为axios的post参数即可,修正后代码:
const fd = new FormData(); fd.append('fname', 'test.webm'); fd.append('data', blob); // 直接传FormData实例,无需嵌套对象 axios.post('/translate-audio', fd) .then(res => console.log(res)) .catch(err => console.error(err));
2. 后端代码错误修正
express自带的express.json()中间件只能处理application/json格式的请求体,无法解析multipart/form-data类型的文件上传请求,需要安装使用multer中间件来处理文件上传。
首先安装依赖:
npm install multer
修正后后端代码:
const cors = require('cors'); const express = require('express'); const multer = require('multer'); // 配置内存存储,适合小音频文件,大文件可替换为磁盘存储配置 const storage = multer.memoryStorage(); const upload = multer({ storage: storage }); const app = express(); app.use(cors()); app.use(express.json()); // upload.single('data')对应FormData中音频的字段名data app.post('/translate-audio', upload.single('data'), async (req, res) => { // 文本字段存储在req.body中 console.log('文件名:', req.body.fname); // 音频文件信息存储在req.file中,buffer为音频二进制数据 console.log('音频文件:', req.file); console.log('音频二进制数据:', req.file.buffer); // 后续业务逻辑 });
不使用FormData的替代方案
如果不想用FormData,可以直接将Blob转为Base64字符串放在JSON请求体中传递:
前端实现
// Blob转Base64工具方法 const blobToBase64 = (blob) => { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.readAsDataURL(blob); reader.onloadend = () => resolve(reader.result); reader.onerror = reject; }); } const base64Audio = await blobToBase64(blob); axios.post('/translate-audio', { fname: 'test.webm', data: base64Audio });
后端实现
app.post('/translate-audio', async (req, res) => { const { fname, data } = req.body; // 去除Base64前缀后转为Buffer即可处理 const audioBuffer = Buffer.from(data.split(',')[1], 'base64'); // 后续业务逻辑 });
注意:Base64编码会让数据体积增大33%左右,仅适合小音频文件,大音频仍推荐使用FormData方案
服务端向前端发送音频Blob的最优实现
最优方案是直接返回二进制流,设置正确的响应头即可,无额外编码开销,传输效率最高:
后端实现
app.get('/get-audio', async (req, res) => { // 你的音频二进制Buffer,可来自本地文件读取、业务处理生成等 const audioBuffer = 音频Buffer数据; // 设置正确的响应头 res.set({ 'Content-Type': 'audio/webm', // 替换为你的实际音频格式 'Content-Length': audioBuffer.length, // 如需前端直接下载可添加以下配置 // 'Content-Disposition': 'attachment; filename="output.webm"' }); // 直接返回二进制Buffer res.send(audioBuffer); });
前端接收处理
axios.get('/get-audio', { responseType: 'blob' // 必须指定响应类型为blob,否则会拿到乱码字符串 }).then(res => { const audioBlob = res.data; // 生成可直接播放的音频地址 const audioUrl = URL.createObjectURL(audioBlob); const audio = new Audio(audioUrl); audio.play(); // 音频使用完毕后释放内存 // URL.revokeObjectURL(audioUrl); });
内容的提问来源于stack exchange,提问作者Michael Han
相关产品推荐
相关产品推荐

