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, )
我的问题
- 在视图函数中,使用
request.form和request.get_json()有什么区别?在我的场景中哪种是最佳实践?另一种的适用场景是什么? - 为什么添加
"Content-Type": "multipart/form-data"请求头后,视图函数无法获取文件,不添加则可以正常工作? - 针对我这种同时上传文件和数据的场景,一般的最佳实现方案是什么?
问题解答
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),方便后续业务调用。
- 在Flask中配置
内容的提问来源于stack exchange,提问作者stevezkw
相关产品推荐
相关产品推荐

