You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React项目调用Node.js保存录音时出现Uncaught (in promise) AxiosError求助

问题分析与修正方案

你的代码存在几个关键问题,导致Axios请求失败和音频无法正确保存:

1. React端(Record.js)的错误修正

核心问题:

  • 请求URL缺少http://协议,浏览器会将其当作相对路径处理
  • 上传的是blobURL(本地URL字符串)而非实际的Blob音频文件,multer无法解析
  • 未捕获Axios请求错误,无法定位具体问题
  • 提前弹出成功提示,无视请求实际状态

修正后的完整代码:

import React from "react";
import MicRecorder from "mic-recorder-to-mp3";
import { Button } from "reactstrap";
import "./App.css";
import Navbar from "./Navbar";
import mic from "./imgs/mic.png";
import stop from "./imgs/stop.png";
import axios from "axios";

const Mp3Recorder = new MicRecorder({ bitRate: 128 });

class Record extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isRecording: false,
      blobURL: "",
      isBlocked: false,
      audioBlob: null, // 新增:存储原始Blob音频对象
    };
  }

  start = () => {
    if (this.state.isBlocked) {
      console.log("Permission Denied");
    } else {
      Mp3Recorder.start()
        .then(() => this.setState({ isRecording: true }))
        .catch((e) => console.error(e));
    }
  };

  stop = () => {
    Mp3Recorder.stop()
      .getMp3()
      .then(([buffer, blob]) => {
        const blobURL = URL.createObjectURL(blob);
        this.setState({ blobURL, isRecording: false, audioBlob: blob }); // 保存原始Blob
      })
      .catch((e) => console.log(e));
  };

  componentDidMount() {
    // 替换废弃的getUserMedia API
    navigator.mediaDevices.getUserMedia({ audio: true })
      .then(() => {
        console.log("Permission Granted");
        this.setState({ isBlocked: false });
      })
      .catch(() => {
        console.log("Permission Denied");
        this.setState({ isBlocked: true });
      });
  }

  Save = async (e) => {
    e.preventDefault();
    if (!this.state.audioBlob) {
      alert("请先录制音频");
      return;
    }

    const url = "http://localhost:8000/record"; // 补充完整协议
    const data = new FormData();
    // 上传原始Blob对象,并指定文件名
    data.append("audio", this.state.audioBlob, `recording_${Date.now()}.mp3`);

    try {
      const response = await axios.post(url, data, {
        headers: { "Content-Type": "multipart/form-data" },
      });
      console.log("上传成功", response.data);
      alert("音频上传成功");
    } catch (error) {
      console.error("上传失败", error);
      alert("音频上传失败,请检查服务器是否运行");
    }
  };

  render() {
    return (
      <div className="big-wrapper light">
        <div className="container">
          <Navbar />
          <br />
          <br />
          <br />
          <div className="cont1">
            <h2 style={{ color: "white", marginLeft: "-98px" }}>
              Remove Noise From Your Audio
            </h2>
            <br />
            <Button
              className="bg-transparent border btn record-button rounded-circle shadow-sm text-center"
              id="recordButton"
              onClick={() => {
                this.state.isRecording ? this.stop() : this.start();
              }}
            >
              {this.state.isRecording ? <img src={stop} /> : <img src={mic} />}
            </Button>
            <br />
            <br />
            <audio
              src={this.state.blobURL}
              controls="controls"
              autoPlay
              id="audio-element"
            />
            <br />
            <br />
            <form
              method="post"
              action="#"
              onSubmit={this.Save}
              className="form-group"
            >
              <button className="btn-recordaudio">Submit</button>
            </form>
          </div>
        </div>
      </div>
    );
  }
}

export default Record;

2. Node.js端(index.js)的错误修正

核心问题:

  • 上传Blob时file.originalname不存在,导致文件名处理出错
  • 未检查uploads目录是否存在,可能导致保存失败
  • 缺少文件上传失败的错误处理

修正后的完整代码:

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 uploadDir = path.join(__dirname, "uploads");
if (!fs.existsSync(uploadDir)) {
  fs.mkdirSync(uploadDir, { recursive: true });
}

const storage = multer.diskStorage({
  destination(req, file, cb) {
    cb(null, uploadDir);
  },
  filename(req, file, cb) {
    // 处理无原始文件名的情况,默认使用mp3后缀
    const ext = path.extname(file.originalname) || ".mp3";
    // 生成唯一文件名,避免覆盖
    cb(null, `recording_${Date.now()}${ext}`);
  },
});

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: `/uploads/${req.file.filename}`
  });
});

app.listen(8000, () => {
  console.log("server is running on http://localhost:8000");
});

3. 测试步骤

  1. 在Node.js服务器目录运行node index.js启动服务
  2. 启动React项目,录制一段音频
  3. 点击Submit按钮,检查uploads目录是否生成音频文件
  4. 查看浏览器控制台,确认无报错信息

内容的提问来源于stack exchange,提问作者Steven

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 23:26:05