React中用mic-recorder-to-mp3录音后,无法通过Express+Multer保存至服务器目录
问题分析与解决方案
核心问题
前端传递给后端的是本地生成的Blob URL字符串而非实际音频文件,导致multer无法识别并存储。此外还有几处细节问题需要修正。
具体修复步骤
1. 前端(RecordAudio.js)修改
- 保存原始Blob对象到状态:停止录制时,同时保存Blob URL和原始Blob对象。
- 提交Blob文件而非URL:将Blob对象添加到FormData中传递给后端,而非Blob URL。
- 添加错误处理逻辑:捕获请求失败场景,避免误提示上传成功。
修改后的关键代码片段:
// 构造函数中新增blob状态 constructor(props) { super(props); this.state = { isRecording: false, blobURL: "", isBlocked: false, blob: null // 存储原始音频Blob }; } // 停止录制时保存Blob对象 stop = () => { Mp3Recorder.stop() .getMp3() .then(([buffer, blob]) => { const blobURL = URL.createObjectURL(blob); this.setState({ blobURL, isRecording: false, blob }); // 保存Blob到状态 }) .catch((e) => console.log(e)); }; // 修正保存方法 Save = (e) => { e.preventDefault(); if (!this.state.blob) { alert("没有可保存的音频"); return; } const url = "http://localhost:8000/record"; const data = new FormData(); // 传递Blob对象并指定文件名 data.append("audio", this.state.blob, "recording.mp3"); axios.post(url, data) .then((res) => { console.log("上传成功", res.data); alert("音频上传成功"); }) .catch((err) => { console.error("上传失败", err); alert("音频上传失败"); }); };
2. 后端(server.js)修改
- 自动创建uploads目录:避免因目录不存在导致multer存储失败。
- 优化文件名处理:兼容文件原始名称无扩展名的情况,默认使用mp3格式。
- 添加文件接收校验:确认multer成功接收文件后再返回成功响应。
修改后的关键代码片段:
const path = require("path"); const fs = require("fs"); const express = require("express"); const multer = require("multer"); const cors = require("cors"); const app = express(); app.use(cors()); app.use(express.static("uploads")); // 确保uploads目录存在,不存在则创建 const uploadsDir = path.join(__dirname, "uploads"); if (!fs.existsSync(uploadsDir)) { fs.mkdirSync(uploadsDir, { recursive: true }); } const storage = multer.diskStorage({ destination(req, file, cb) { cb(null, uploadsDir); // 使用绝对路径更可靠 }, filename(req, file, cb) { // 处理扩展名,默认使用mp3 let extension = "mp3"; if (file.originalname && file.originalname.includes(".")) { extension = file.originalname.split(".").pop(); } cb(null, `recording.${extension}`); }, }); const upload = multer({ storage }); app.post("/record", upload.single("audio"), (req, res) => { if (!req.file) { return res.status(400).json({ success: false, message: "未接收到音频文件" }); } res.json({ success: true, filePath: req.file.path, fileName: req.file.filename }); }); app.listen(8000, () => { console.log("服务器运行在8000端口"); });
验证步骤
- 重启后端服务
- 录制音频后点击保存,检查uploads目录下是否生成音频文件
- 查看浏览器控制台和后端日志,确认无错误信息
内容的提问来源于stack exchange,提问作者Steven
相关产品推荐
相关产品推荐

