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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 16:25:18