Python FastAPI 422 Unprocessable Entity报错排查实录 error:Invalid \\escape

问题

前端调 FastAPI 的 /document/parse-path 接口,直接甩回来这么一坨:

HTTP 422 Unprocessable Entity 。不是 500 后端炸了,是请求体根本没通过验证。


报错解释

|--------------------|------------------------------------------------|
| 字段 | 含义 |
| 422 | FastAPI/Pydantic 的请求体验证失败(请求格式问题) |
| json_invalid | JSON 本身解析就挂了,还没到 Pydantic 那一步 |
| Invalid \\escape | JSON 里反斜杠 \ 只能当转义前缀(\n \t \\ \uXXXX),不能瞎用。 |

情况是这样的。 前端传了一个 Windows 绝对路径:

复制代码
{ "file_path": "D:\data\uploads\report.pdf" }

JSON 解析器看到 \u 以为是 unicode 转义的开头(\uXXXX),实际并不是,所以直接炸。


原因

JSON 转义报错是表面问题 ,本质是之前后端逼前端传Windows绝对路径 ------而它天生带\,踩JSON转义坑是必不可免的,就算这次让前端转义成\\,下次换个前端 / 工具还会栽。

解决

加路径分流 :让前端可以根本不传带反斜杠的路径,只传裸文件名就行------连反斜杠都碰不到,转义问题直接没了,顺便还让前端不用关心后端上传目录,接口更友好。


改动

改了 3 处,全在 document.py 里:

改动 1:新增路径分流逻辑

java 复制代码
input_path = body.file_path

if os.path.dirname(input_path):
    # dirname 返回非空 → 传的是完整路径(带目录),直接用
    target_path = input_path
else:
    # dirname 返回空串 → 只有裸文件名,拼到上传目录
    upload_dir = _ensure_upload_dir()
    target_path = os.path.join(upload_dir, input_path)

关键函数 os.path.dirname()一行解决跨平台判断:

os.path.dirname(path) :返回路径中"最后一个斜杠之前"的部分,也就是目录部分。

|--------------------------------|---------------------|--------|
| 输入 | dirname() 返回 | 说明 |
| "D:\data\uploads\report.pdf" | "D:\data\uploads" | ✅ 完整路径 |
| "data/uploads/report.pdf" | "data/uploads" | ✅ 完整路径 |
| "report.pdf" | ""(空串) | ❌ 裸文件名 |

改动 2:新增 _ensure_upload_dir() 辅助函数

java 复制代码
def _ensure_upload_dir():
    """确保上传目录存在"""
    upload_dir = Path(settings.UPLOAD_DIR)         # 获取上传目录路径
    upload_dir.mkdir(parents=True, exist_ok=True)  # 创建目录
    return upload_dir
  • parents=True:如果 data/uploads/ 里上级目录不存在,递归创建 (类似 mkdir -p);
  • exist_ok=True:目录已经存在也不报错

改动 3:提前校验文件是否存在

java 复制代码
if not os.path.isfile(target_path):
        raise HTTPException(status_code=404, detail=f"文件不存在: {target_path}")

原来直接扔给解析器 → 解析器抛异常 → 给 500。现在提前拦截,给调用方一个清晰的 404 ✨


完整调用流程

复制代码
POST /document/parse-path
  body: { "file_path": "report.pdf" }   ← 裸文件名,根本没 \ !
         │
         ▼
  os.path.dirname("report.pdf") → ""  ← falsy!走 else 分支
         │
         ▼
  _ensure_upload_dir()
    Path(settings.UPLOAD_DIR) + mkdir(parents, exist_ok)
         │
         ▼
  os.path.join(upload_dir, "report.pdf")
    → "data/uploads/report.pdf"  ← 跨平台安全拼接
         │
         ▼
  os.path.exists()?  ──NO──▶ 404 错误(友好提示)
         │
        YES
         │
         ▼
  parse_file(target_path) 解析
         │
         ▼
  返回 chunks / tables / 统计信息

💡 思路总结

以后写++"接收路径参数"的接口++,按这个顺序过一遍:

  1. 调用方可能传什么? → 完整绝对路径?还是裸文件名?
  2. 怎么区分? → os.path.dirname()
  3. 裸文件名去哪找? → 拼到 settings 里预先配置的上传目录(不要硬编码)
  4. 目录不存在咋办? → pathlib.Path.mkdir(parents=True, exist_ok=True) 自动建,抽个辅助函数
  5. 文件不存在咋办? → 提前检查,返回 404 而不是让解析器炸 500

就这 5 步,本质是给调用方提供了两种输入方式。

相关推荐
溪语流沙6 小时前
【Web全栈进阶】Nginx反向代理 + HTTPS:正式上线
前端·vue.js·python·nginx·https·fastapi
肖永威8 小时前
python版微电网仿真工具的前端托管选型:从http.server到FastAPI StaticFiles
前端·python·http·fastapi
七点半.18 小时前
FastAPI · SSE · async/await
fastapi·sse
张张123y2 天前
后端第十一课:RAG 落地实战(从 0 到 1 接上私有知识库,并设计一个好用的 RAG)
开发语言·人工智能·python·机器学习·fastapi·rag
云水初2 天前
【项目篇】基于LanGraph的自动处理客服邮件的 Agent汇总
开发语言·笔记·python·学习·fastapi·langgraph
溪语流沙2 天前
【Web全栈进阶】文件上传与图片展示:早报站的第一张图片
前端·vue.js·python·fastapi
今年下半年4 天前
AI智能体项目实战记录(02):初始化 Python 项目
开发语言·人工智能·python·fastapi
溪语流沙4 天前
【Web全栈进阶】前端对接新契约:信封解包 + 统一错误处理
前端·vue.js·python·状态模式·fastapi
像风一样自由20205 天前
56.实战PostgreSQL-pgvector-FastAPI构建轻量级RAG
数据库·人工智能·postgresql·大模型·fastapi·智能体