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

FastAPI含参数与文件上传接口持续返回422错误求助

问题

我定义了一个支持文件上传与参数接收的FastAPI接口,通过Swagger界面调用时可正常将3个参数存入数据库并完成文件上传。但编写Pytest测试用例模拟请求时,FastAPI持续返回422错误,错误信息为:

{"detail":[{"loc":["body","file"],"msg":"field required","type":"value_error.missing"}]}

参数模型

class PcapCreate(BaseModel):
    """
    API schema for posting a new file.
    """

    test_run_id: uuid.UUID
    component_id: uuid.UUID
    pcap_create_user: uuid.UUID

端点代码

from fastapi import APIRouter, status, File, UploadFile, Depends
from fastapi.responses import JSONResponse

from core.responses import APIResponse
from models.pcaps import Pcaps
from models.pcapcreate import PcapCreate
from models.ack import ACK
from models.nack import NACK

@router.post(
    "/",
    summary="upload a new pcap file",
    description="Uploads a new pcap file.",
    response_model=ACK,
    name="pcaps:create-pcap",
    status_code=status.HTTP_201_CREATED,
    responses={404: {"model": NACK}},
)
async def upload_pcap(
        pcap: PcapCreate = Depends(),
        file: UploadFile = File(...),
) -> JSONResponse:
    """
    Endpoint view for uploading a new file.
    """
    instance = await Pcaps(**pcap.dict(exclude_unset=True)).save()

    pcap_id = str(instance.pcap_id)

    ... code for saving file to disk.

    success_text: str = "success"
    ack_message: dict = APIResponse.ack(pcap_id, success_text)

    return JSONResponse(
        status_code=status.HTTP_201_CREATED, content=ack_message
    )

测试代码

import pytest
from fastapi import FastAPI, status
from httpx import AsyncClient

async def test_endpoint_create_valid_pcap_201(
    app: FastAPI,
    client: AsyncClient,
) -> None:
    """
    Tests if a POST request with a file upload returns a 201 response.
    """
    files = {
        'file': open('tests/test.pcap', 'rb'),
    }
    params = {
        "test_run_id": "e3db3e6d-f3db-4d9a-8db5-9ee3e3396ff9",
        "component_id": "d060307d-8b84-44b4-848d-4bd910219d92",
        "pcap_create_user": "6f3300ac-d478-4aa1-8316-c6f30b8402ce",
    }

    response = await client.post(
        app.url_path_for("pcaps:create-pcap"),
        params=params,
        files=files
    )
    print(response.url)
    print(response.text)
    assert response.status_code == status.HTTP_201_CREATED

解决方案

问题原因

  1. 参数传递方式错误:端点中PcapCreate参数通过Depends()接收,由于接口包含文件上传,FastAPI会自动使用multipart/form-data编码,此时模型参数需要从表单数据中解析,但测试代码把这些参数放在了params(URL查询参数)中,不符合接口的解析逻辑。
  2. FastAPI参数解析规则:当接口同时包含File和Depends()模型参数时,所有非文件参数必须作为表单字段传递,而非URL查询参数。

修改测试代码

将原params中的参数移到data参数中传递(作为表单字段),同时保留文件字段:

import pytest
from fastapi import FastAPI, status
from httpx import AsyncClient

async def test_endpoint_create_valid_pcap_201(
    app: FastAPI,
    client: AsyncClient,
) -> None:
    """
    Tests if a POST request with a file upload returns a 201 response.
    """
    # 表单参数单独放在data字典中
    data = {
        "test_run_id": "e3db3e6d-f3db-4d9a-8db5-9ee3e3396ff9",
        "component_id": "d060307d-8b84-44b4-848d-4bd910219d92",
        "pcap_create_user": "6f3300ac-d478-4aa1-8316-c6f30b8402ce",
    }
    
    # 使用with语句管理文件资源,避免泄漏
    with open('tests/test.pcap', 'rb') as f:
        files = {'file': f}
        response = await client.post(
            app.url_path_for("pcaps:create-pcap"),
            data=data,
            files=files
        )
    
    print(response.url)
    print(response.text)
    assert response.status_code == status.HTTP_201_CREATED

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 13:32:46