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

Flask中request.form与request.get_json()区别及文件上传问题咨询

场景描述

我编写了一个Flask视图函数,用于处理包含文件和数据的POST请求:

@app.route('/auth/audio/save', methods=['POST'])
def save_audio():
    # files = request.files
    resp_dict = {'message': "success"}
    file = request.files.get("file")
    if file.filename == "":
        resp_dict['message'] = "[No file] file.filename == ''"
        return jsonify(resp_dict), 400
    # data = request.get_json()
    data = request.form
    logger.info(f"data: {data}")
    check_required_params(data, ['user_id'])
    user_id = data["user_id"]
    audio_dir = os.path.join(app_dir, 'db_files/audio')
    save_path = os.path.join(audio_dir, f'{user_id}.bin')
    file.save(save_path)
    return jsonify(resp_dict), 200

请求发送端的代码如下:

def test_send_audio():
    cur_dir = os.path.dirname(os.path.abspath(__file__))
    audiopath = os.path.join(cur_dir, "test.wav")
    files = {'file': open(audiopath, 'rb')}
    data = {"user_id": 2}
    # headers = {
    #     "Content-Type": "multipart/form-data",
    # }
    # NOTE: Not sure why handlers can't get files when I add headers
    response = requests.post(
        save_audio_url,
        # headers=headers,
        files=files,
        data=data,
    )
我的问题
  1. 在视图函数中,使用request.form和request.get_json()有什么区别?在我的场景中哪种是最佳实践?另一种的适用场景是什么?
  2. 为什么添加"Content-Type": "multipart/form-data"请求头后,视图函数无法获取文件,不添加则可以正常工作?
  3. 针对我这种同时上传文件和数据的场景,一般的最佳实现方案是什么?
问题解答

1. request.form与request.get_json()的区别及适用场景

  • request.form:专门解析multipart/form-data或application/x-www-form-urlencoded格式的请求体,这两种都是表单提交的标准格式。前者支持文件上传,后者对应普通键值对表单。你的场景需要同时传文件和表单字段,用的是multipart/form-data格式,所以request.form是正确选择。
  • request.get_json():仅解析application/json格式的请求体,也就是纯JSON字符串数据。适合纯结构化数据的API接口场景,比如前后端分离中不需要上传文件、只传JSON参数的接口。

2. 手动添加Content-Type导致无法获取文件的原因

当用requests.post同时传入files和data参数时,requests会自动生成完整的multipart/form-data请求头,其中包含关键的boundary分隔符——这个分隔符用来区分请求体里的文件、表单字段等不同部分。

如果手动指定"Content-Type": "multipart/form-data",这个头里没有携带boundary信息,Flask后端无法正确拆分请求体内容,自然识别不到文件和表单数据。

3. 同时上传文件和数据的最佳实践

  • 后端处理:
    • 用request.files.get("file")获取文件对象,先校验文件名是否为空、文件格式是否合法;
    • 用request.form读取表单字段,保留参数校验逻辑(比如你的check_required_params);
    • 提前创建文件存储目录,可加os.makedirs(audio_dir, exist_ok=True)避免目录不存在报错;
    • 捕获文件保存时的异常(如权限不足、磁盘已满),返回对应的错误信息和状态码。
  • 请求端处理:
    • 直接使用requests的files和data参数,不要手动设置Content-Type,让requests自动生成带boundary的正确请求头;
    • 打开文件用with语句保证资源正确释放:with open(audiopath, 'rb') as f: files = {'file': f}。
  • 额外建议:
    • 在Flask中配置MAX_CONTENT_LENGTH限制上传文件大小;
    • 校验上传文件的后缀,仅允许指定音频格式(如.wav);
    • 响应中可返回文件存储标识(如文件ID),方便后续业务调用。

内容的提问来源于stack exchange,提问作者stevezkw

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 11:44:57