Flask与JavaScript实现Blob音频文件提交问题求助
嗨,我来帮你理清楚问题出在哪,以及怎么解决~
问题根源拆解
你现在遇到的Bad Request错误,主要是两个核心问题导致的:
- 原表单提交无效:你的表单里只有一个提交按钮,完全没有把录制好的Blob音频数据添加到表单中,点击submit时服务器根本没收到任何音频文件。
- Ajax请求格式错误:你直接把
blob作为请求数据发送,但没有用FormData对象包装——这是浏览器上传文件的标准格式,不符合规范的话,Flask的request.files就识别不到你的音频数据,自然报Bad Request。
修正后的完整实现
下面是调整后的前后端代码,一步步帮你解决问题:
1. 前端代码(录音+提交逻辑)
我们会把录制好的Blob存起来,点击提交时用FormData包装后发送,同时加入错误提示和麦克风资源释放:
<form> <div class="audio" id="audio"></div> <button type="button" id="submitBtn">提交录音</button> </form> <script type="text/javascript"> // 全局变量保存录制好的音频Blob let recordedBlob = null; // 请求麦克风权限并开始录制 navigator.mediaDevices.getUserMedia({audio: true}) .then(stream => { const recorder = new MediaRecorder(stream); const audioChunks = []; recorder.ondataavailable = e => { audioChunks.push(e.data); if (recorder.state === 'inactive') { // 生成完整的音频Blob recordedBlob = new Blob(audioChunks, {type: 'audio/webm'}); // 创建预览音频元素 const audioContainer = document.getElementById('audio'); const previewAudio = document.createElement('audio'); previewAudio.controls = true; previewAudio.src = URL.createObjectURL(recordedBlob); audioContainer.appendChild(previewAudio); } }; recorder.start(100); // 5秒后自动停止录制,并释放麦克风资源 setTimeout(() => { recorder.stop(); stream.getTracks().forEach(track => track.stop()); }, 5000); }) .catch(err => { console.error('获取麦克风权限失败:', err); alert('请允许浏览器访问麦克风才能录制音频'); }); // 提交按钮点击事件 document.getElementById('submitBtn').addEventListener('click', () => { if (!recordedBlob) { alert('还没有录制音频哦,请等待录制完成'); return; } // 用FormData包装音频文件,这是上传文件的标准方式 const formData = new FormData(); // 第一个参数是字段名,要和后端的字段名对应,这里叫'recorded_audio' formData.append('recorded_audio', recordedBlob, 'my_recording.webm'); // 用fetch发送请求(也可以用jQuery的$.ajax,逻辑一致) fetch('/send', { method: 'POST', body: formData }) .then(response => response.json()) .then(result => { console.log('服务器响应:', result); alert('录音提交成功!'); }) .catch(err => { console.error('提交失败:', err); alert('提交出错了,请检查网络或重试'); }); }); </script>
2. Flask后端代码
后端要对应前端的字段名来获取文件,同时做一些健壮性处理:
from flask import Flask, request, jsonify import os app = Flask(__name__) # 确保保存录音的目录存在 os.makedirs('recordings', exist_ok=True) @app.route('/send', methods=['POST']) def submit_audio(): if request.method == 'POST': # 这里的'recorded_audio'要和前端formData.append的第一个参数完全一致 audio_file = request.files.get('recorded_audio') if not audio_file: return jsonify({'error': '未收到音频文件'}), 400 # 打印调试信息,确认收到文件 app.logger.debug(f'收到文件:{audio_file.filename},类型:{audio_file.content_type}') # 保存音频文件到服务器(根据你的需求选择是否保存) audio_file.save(os.path.join('recordings', audio_file.filename)) return jsonify({'message': '音频提交成功'}), 200 if __name__ == '__main__': app.run(debug=True)
关键知识点补充
- FormData的作用:它是浏览器专门用来构建
multipart/form-data格式请求的对象,只有用它包装文件,后端才能通过request.files获取到上传的文件。 - 字段名一致性:前端
formData.append('xxx', blob)里的xxx,必须和后端request.files.get('xxx')里的xxx完全一致,否则后端找不到对应的文件。 - 麦克风资源释放:录制停止后记得调用
stream.getTracks().forEach(track => track.stop()),否则浏览器会一直占用麦克风,导致下次录制可能出问题。
内容的提问来源于stack exchange,提问作者anonimostilton
相关产品推荐
相关产品推荐

