Flask提交30秒WebM音频遇413请求实体过大问题排查
解决Flask提交音频时的413 Request Entity Too Large错误
核心问题分析
你将WebM音频转成DataURL(base64编码)后,文件体积会膨胀约33%——650KB的原文件会变成~867KB的字符串,放在表单的audio_data字段中提交。此时触发的并非整个请求体大小限制,而是单个表单字段的大小限制,或是Werkzeug(Flask依赖的WSGI工具库)的表单内存解析限制。
解决方案
方案1:改用FormData直接上传Blob(推荐)
放弃base64转码,直接用FormData提交原始Blob,既避免体积膨胀,又绕过表单字段大小限制:
前端代码修改
function processRecording() { let audioBlob = new Blob(audioChunks, { type: 'audio/webm' }); let formData = new FormData(); formData.append('audio_file', audioBlob, 'recording.webm'); fetch('/speaking_task_submit', { method: 'POST', body: formData }).then(response => { response.ok ? console.log('提交成功') : response.json().then(err => console.error(err)); }).catch(err => console.error(err)); }
后端代码修改
from flask import request, jsonify import os @app.route('/speaking_task_submit', methods=['POST']) def speaking_task_submit(): print(f"Flask MAX_CONTENT_LENGTH: {app.config.get('MAX_CONTENT_LENGTH')} bytes") print(f"Received Content-Length: {request.content_length} bytes") if 'audio_file' not in request.files: return jsonify({"error": "未上传音频文件"}), 400 audio_file = request.files['audio_file'] if audio_file.filename == '' or audio_file.content_type != 'audio/webm': return jsonify({"error": "仅支持WebM格式音频"}), 400 os.makedirs('uploads', exist_ok=True) audio_file_path = os.path.join('uploads', 'candidate_audio.webm') audio_file.save(audio_file_path) return jsonify({"message": "音频接收成功"})
方案2:调整Werkzeug表单内存限制(若坚持用DataURL)
Werkzeug默认限制表单数据在内存中的大小为1MB,超过后会尝试写入临时文件,但单个字段过大仍可能触发错误。通过Flask配置调整:
app.config['MAX_CONTENT_LENGTH'] = 100 * 1024 * 1024 # 100MB总请求限制 app.config['WERKZEUG_MAX_FORM_MEMORY_SIZE'] = 10 * 1024 * 1024 # 10MB表单内存限制
方案3:确保Gunicorn配置正确加载
启动Gunicorn时必须明确指定配置文件,否则你的gunicorn_config.py不会生效:
gunicorn --config gunicorn_config.py your_app_module:app
可在配置文件中添加日志验证加载状态:
# gunicorn_config.py import logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) limit_request_field_size = 0 limit_request_line = 0 timeout = 300 worker_connections = 1000 logger.info(f"加载配置:limit_request_field_size={limit_request_field_size}")
方案4:绕过Flask表单解析(Waitress/Gunicorn通用)
直接读取原始请求体,避免表单解析的字段限制:
from flask import request, jsonify import base64 import os @app.route('/speaking_task_submit', methods=['POST']) def speaking_task_submit(): raw_data = request.get_data().decode('utf-8') try: audio_data = raw_data.split('audio_data=')[1].replace('+', ' ') audio_content = base64.urlsafe_b64decode(audio_data.split(',')[1]) except (IndexError, ValueError): return jsonify({"error": "音频数据无效"}), 400 os.makedirs('uploads', exist_ok=True) with open('uploads/candidate_audio.webm', 'wb') as f: f.write(audio_content) return jsonify({"message": "音频接收成功"})
额外排查点
- 查看终端输出的
Received Content-Length值,确认实际请求大小是否符合预期。 - 用Postman直接提交大体积表单字段,排除前端编码问题。
内容的提问来源于stack exchange,提问作者Gavin Reid
相关产品推荐
相关产品推荐

