React中使用Amplify上传音频Blob至AWS S3后文件无法使用
问题分析与解决办法
核心问题
- 点击事件逻辑错误:
onClick={AplS3(mediaBlobUrl)}会在组件渲染时立即执行上传函数,而非点击按钮时触发,还可能传递无效/未就绪的Blob URL。 - 格式标识与内容不匹配:浏览器MediaRecorder默认录制格式为
audio/webm(Chrome等主流浏览器),你强制将File的type设为audio/mpeg,但文件实际内容仍是webm格式,导致S3上的文件格式标识和实际内容不符,无法正常播放。 - 冗余的Blob转换流程:从Blob URL通过
fetch再转Blob完全没必要,反而可能引入数据处理错误。
修正方案
直接利用ReactMediaRecorder的whenStopped回调获取原始录制Blob,存储到组件状态后再上传,保留正确的文件格式:
import { useState } from 'react'; import ReactMediaRecorder from 'react-media-recorder'; import { Storage } from 'aws-amplify'; const AudioS3 = () => { const [recordedBlob, setRecordedBlob] = useState(null); const uploadToS3 = async () => { if (!recordedBlob) return; // 基于原始Blob创建File,保留真实MIME类型 const file = new File([recordedBlob], `audio-${Date.now()}.webm`, { type: recordedBlob.type }); try { await Storage.put(`Audio_test/${file.name}`, file, { contentType: recordedBlob.type, level: "protected" }); console.log("上传成功"); } catch (err) { console.log("文件上传错误", err); } }; return ( <div> <ReactMediaRecorder audio whenStopped={(blobUrl, blob) => { console.log(blobUrl); setRecordedBlob(blob); // 保存录制得到的原始Blob }} render={({ status, startRecording, stopRecording, mediaBlobUrl }) => ( <div> <p>{status}</p> <button onClick={startRecording}>开始录制</button> <button onClick={stopRecording}>停止录制</button> {mediaBlobUrl && <audio src={mediaBlobUrl} controls autoPlay />} {/* 录制完成后才启用上传按钮 */} <button onClick={uploadToS3} disabled={!recordedBlob} > 上传录制文件 </button> </div> )} /> </div> ); }; export default AudioS3;
额外说明
- 如果必须上传MP3格式,浏览器原生MediaRecorder不支持直接录制MP3,需要引入第三方编码库(如
lamejs)将webm格式的Blob编码为MP3后再上传。 - 上传时指定的
contentType必须和文件实际格式一致,否则浏览器会无法正确识别并播放S3返回的文件。
内容的提问来源于stack exchange,提问作者SAM.Am
相关产品推荐
相关产品推荐

