根本原因是request.body为一次性流,被request.get_json()、request.form等方法提前读取耗尽;flask应使用request.get_data(cache=true),django需在访问request.post前读取并手动缓存。

为什么 request.body 读出来是空字节或乱码
常见于 Flask 或 Django 接收 JSON 请求时,request.body 看似可读但实际为空、为 b'',或解码后是乱码。根本原因不是代码写错了,而是请求体已被提前消费——比如你调用了 request.get_json()、request.form、request.json 或任何触发底层 read() 的方法,之后再读 request.body 就会返回空。
Flask 的 request.body 是一次性的流(BytesIO),读完即耗尽;Django 的 request.body 同理,底层是 io.BytesIO 缓冲区,不可重复读取。
- 检查是否在读
request.body前调用了request.get_json()、request.data(Django 中等价于body)、request.form或request.files - Flask 中
request.json和request.get_json()都会自动解析并隐式读取 body,之后request.body就空了 - Django 中只要访问过
request.POST或request.FILES,也会触发对body的解析和清空(尤其当Content-Type是application/x-www-form-urlencoded或multipart/form-data)
想原始读取又兼容 JSON 解析,该用哪个字段
目标明确:既要拿到原始字节做签名验签、日志记录、中间件透传,又要能正常解析 JSON 数据。不能靠反复读 request.body,得换思路。
- Flask:优先用
request.get_data(cache=True)—— 它会缓存首次读取结果,后续调用都返回同一份原始字节;再用json.loads(request.get_data())解析,安全且不冲突 - Django:直接用
request.body(仅限一次),但必须放在所有request.POST/request.FILES访问之前;若需多次使用,手动缓存:raw_body = request.body; json.loads(raw_body) - 注意
cache=True在 Flask 中默认为False,漏写就等于没用;Django 没有类似机制,必须自己控制访问顺序
Content-Type 不匹配导致读取失败的典型表现
即使 body 没被消费,request.get_json() 或 json.loads(request.body) 仍可能报 JSONDecodeError 或返回 None,大概率是客户端发的 Content-Type 和服务端预期不一致。
- Flask
request.get_json()默认只响应application/json;如果前端发的是text/plain或没带 header,它直接返回None,不会尝试解析 - Django 的
request.body不校验类型,但json.loads()会因内容非合法 JSON 报错;常见于前端用JSON.stringify()但漏加Content-Type: application/json,后端却按表单逻辑处理 - 调试时先打印
request.content_type(Flask)或request.META.get('CONTENT_TYPE')(Django),再对比实际请求 payload 是否真为 JSON 格式(比如有没有多余逗号、单引号代替双引号)
中间件/装饰器里读 body 的坑
在 Flask 的 before_request 或 Django 的中间件中记录原始请求体,最容易踩空读、重复读、编码错三连。
- Flask 中间件里别用
request.json,改用request.get_data(cache=True)并保存到g.raw_body供后续视图使用 - Django 中间件中,
process_request阶段可安全读request.body,但必须确保不在process_view或视图里再碰request.POST,否则可能因解析逻辑冲突导致 body 被重置 - 统一用
utf-8解码:request.get_data().decode('utf-8'),避免系统 locale 影响;Django 的request.body原生是 bytes,不 decode 直接转 str 会带b'...'前缀
最麻烦的其实是 multipart 场景:一旦有文件上传,request.body 就没法直接 JSON 解析了,得靠 request.files 和 request.form 分离读取——这种情况下,原始 body 本身就不该被当 JSON 处理。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











