上传音频文件至AWS S3异常:文件大小固定为155 B
问题原因分析
你遇到的问题核心在于二进制音频文件的传输和处理逻辑完全错误,最终上传到S3的不是真实音频数据,而是Blob对象的序列化字符串(155B正是这个字符串的固定长度)。具体问题点:
- 前端用
require导入音频文件时,在Webpack这类打包工具环境下,返回的是文件的访问URL,而非二进制文件内容。 - 将Blob对象直接传入
JSON.stringify,会把Blob序列化成仅包含type、size等元数据的普通对象,所有二进制内容全部丢失。 - 后端将这个序列化后的对象字符串转成Buffer上传,自然无法得到真实音频文件。
修复方案
前端修复:正确读取并传输二进制音频
放弃JSON传输,改用FormData传递二进制文件,同时正确读取音频的二进制内容:
场景1:本地静态音频文件
try { // 用fetch读取本地音频的二进制内容 const audioRes = await fetch("assets/hello.wav"); const audioBlob = await audioRes.blob(); const formData = new FormData(); formData.append("audio", audioBlob, "hello.wav"); formData.append("cloneId", cloneId); await customFetch(`${API_URL}/new-audio-message`, { method: "POST", body: formData, // 无需手动设置Content-Type,浏览器会自动生成正确的multipart/form-data请求头 }); } catch (error) { console.log(error); }
场景2:用户上传的File对象
如果是用户通过<input type="file">选择的音频文件,直接使用File对象即可:
// 假设file是用户选择的File对象 const formData = new FormData(); formData.append("audio", file); formData.append("cloneId", cloneId); // 后续请求代码同上
后端修复:正确解析FormData并上传S3
后端需要解析multipart/form-data格式的请求体,提取音频的二进制数据再上传。以下是两种常见场景的实现:
场景1:AWS Lambda环境
先安装解析依赖:
npm install aws-lambda-multipart-parser
修改后端代码:
const parser = require("aws-lambda-multipart-parser"); const { v4: uuidv4 } = require("uuid"); exports.handler = async (event) => { try { // 解析multipart请求体 const formData = parser.parse(event); const { audio, cloneId } = formData; const sub = "your-sub-value"; // 替换为实际的sub值 const fileKey = `${sub}/${cloneId}/audio/${uuidv4()}.wav`; await s3.putObject({ Bucket: PUBLIC_BUCKET, Key: fileKey, Body: audio.content, // audio.content是文件的二进制Buffer ContentType: audio.contentType, // 自动获取文件MIME类型 }).promise(); return { statusCode: 200, body: "上传成功" }; } catch (err) { console.error(err); return { statusCode: 500, body: "上传失败" }; } };
场景2:Express等Node.js Web框架
使用multer处理文件上传:
npm install multer
修改后端代码:
const multer = require("multer"); const upload = multer(); app.post("/new-audio-message", upload.single("audio"), async (req, res) => { try { const { cloneId } = req.body; const audioFile = req.file; const sub = "your-sub-value"; const fileKey = `${sub}/${cloneId}/audio/${uuidv4()}.wav`; await s3.putObject({ Bucket: PUBLIC_BUCKET, Key: fileKey, Body: audioFile.buffer, ContentType: audioFile.mimetype, }).promise(); res.status(200).send("上传成功"); } catch (err) { console.error(err); res.status(500).send("上传失败"); } });
内容的提问来源于stack exchange,提问作者roger staxx
相关产品推荐
相关产品推荐

