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

Swagger UI无法正确处理可选上传文件?技术问题咨询

问题:FastAPI可选文件参数在Swagger UI请求报错,curl却正常

基于FastAPI定义了POST接口/evaluate,包含必填表单参数server_id和可选文件参数csv_file,代码如下:

from fastapi import FastAPI, File, Form, UploadFile
from typing import Optional
from fastapi.responses import JSONResponse

app = FastAPI()

@app.post("/evaluate")
async def evaluate(
    server_id: str = Form(...),
    csv_file: Optional[UploadFile] = File(None)  # Optional CSV file
):
    if csv_file:
        return JSONResponse(content={
            "server_id": server_id,
            "csv_file_name": csv_file.filename
        })
    else:
        return JSONResponse(content={
            "server_id": server_id,
            "csv_file_name": "No CSV file provided"
        })

安装依赖命令:

pip install fastapi uvicorn python-dotenv python-multipart

启动服务命令:

uvicorn main:app --reload

使用curl请求时,无论是否携带文件都能正常响应:

  • 不带文件的请求:
$ curl -X 'POST' 'http://127.0.0.1:8000/evaluate' -H 'accept: application/json' -F 'server_id=123'

响应:

{"server_id":"123","csv_file_name":"No CSV file provided"}
  • 带文件的请求:
$ curl -X 'POST' 'http://127.0.0.1:8000/evaluate' -H 'accept: application/json' -F 'server_id=123' -F 'csv_file=@nada.csv'

响应:

{"server_id":"123","csv_file_name":"nada.csv"}

但通过Swagger UI发起不带csv文件的请求时,会返回422 Unprocessable Entity错误,响应体如下:

{
  "detail": [
    {
      "type": "value_error",
      "loc": [
        "body",
        "csv_file"
      ],
      "msg": "Value error, Expected UploadFile, received: <class 'str'>",
      "input": "",
      "ctx": {
        "error": {}
      }
    }
  ]
}

提问:这是代码存在问题,还是Swagger UI本身无法处理这种可选文件场景?


原因与解决方案

原因

不是代码本身的问题,是Swagger UI的行为特性导致的:当你在Swagger UI的表单中不选择文件时,它不会省略csv_file这个参数,而是会发送一个空字符串作为该参数的值。而FastAPI收到空字符串后,无法将其解析为UploadFile类型,因此抛出422类型错误。

而curl请求中如果不指定csv_file参数,FastAPI会正确使用你定义的默认值None,所以能正常响应。

解决方案

你可以通过自定义依赖项来处理Swagger UI发送的空值,将其转换为None,修改后的代码如下:

from fastapi import FastAPI, File, Form, UploadFile, Depends
from typing import Optional
from fastapi.responses import JSONResponse

app = FastAPI()

def get_optional_file(file: Optional[UploadFile] = File(None)) -> Optional[UploadFile]:
    # 处理Swagger UI发送的空文件(filename为空字符串的情况)
    if file and file.filename == "":
        return None
    return file

@app.post("/evaluate")
async def evaluate(
    server_id: str = Form(...),
    csv_file: Optional[UploadFile] = Depends(get_optional_file)
):
    if csv_file:
        return JSONResponse(content={
            "server_id": server_id,
            "csv_file_name": csv_file.filename
        })
    else:
        return JSONResponse(content={
            "server_id": server_id,
            "csv_file_name": "No CSV file provided"
        })

这样修改后,无论是curl请求还是Swagger UI请求,不带文件时都能正常返回预期结果。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 12:32:04