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

FastAPI POST接口含可选参数返回400错误(OpenAI应用)

问题原因分析

  1. 请求格式不匹配:

    • 你的process_user_query函数中,text参数默认被识别为查询参数(未用Body或Pydantic模型标记),但调用时用requests.post发送了JSON数组[{"text": "..."}],FastAPI无法解析这种格式,直接返回400错误。
    • 当端点包含UploadFile参数时,FastAPI默认要求请求为multipart/form-data格式,但你发送的是application/json格式,也会导致参数解析失败。
  2. 参数定义与调用不匹配:

    • 未明确text参数的来源(JSON体/查询参数/表单),FastAPI无法正确绑定参数。
    • 调用时的payload是数组结构,但端点期望单个键值对。

解决方案

方案1:拆分端点,分别处理文本与文件请求

拆分端点让逻辑更清晰,分别支持JSON文本请求和文件上传请求:

后端代码修改

from dotenv import load_dotenv
load_dotenv()

from fastapi import APIRouter, HTTPException, UploadFile, File, Body
import base64
import os
from ai_interaction.prompt import assemble_prompt
from ai_interaction.llm import stream_openai_response

router = APIRouter()

# 处理JSON格式的文本请求
@router.post("/query/text")  
async def process_text_query(text: str = Body(...)):
    print("Received text:", text)
    api_key = os.getenv("OPENAI_API_KEY")
    if not api_key:
        raise HTTPException(status_code=500, detail="API key not configured.")

    if not text:
        raise HTTPException(status_code=400, detail="No text provided.")

    image_url = text  # 后续可添加URL验证逻辑
    prompt = assemble_prompt(image_url)
    response = await stream_openai_response(prompt, api_key)
    return {"response": response}

# 处理multipart格式的文件上传请求
@router.post("/query/file")  
async def process_file_query(file: UploadFile = File(...)):
    print("Received file:", file)
    api_key = os.getenv("OPENAI_API_KEY")
    if not api_key:
        raise HTTPException(status_code=500, detail="API key not configured.")

    if not file:
        raise HTTPException(status_code=400, detail="No file provided.")

    image_url = await process_uploaded_file(file)
    prompt = assemble_prompt(image_url)
    response = await stream_openai_response(prompt, api_key)
    return {"response": response}

async def process_uploaded_file(file: UploadFile):
    content = await file.read()
    base64_encoded = base64.b64encode(content).decode('utf-8')
    file_url = f"data:{file.content_type};base64,{base64_encoded}"
    await file.close()
    return file_url 

文本请求调用代码

import requests

url = "http://localhost:8000/api/query/text"
payload = {"text": "Explain the water molecule structure"}
response = requests.post(url, json=payload)
print("Status Code:", response.status_code)
print("Response Body:", response.json())

文件上传调用代码

import requests

url = "http://localhost:8000/api/query/file"
files = {"file": open("your_image.jpg", "rb")}
response = requests.post(url, files=files)
print("Status Code:", response.status_code)
print("Response Body:", response.json())

方案2:单个端点同时支持表单文本与文件上传

如果必须用同一个端点,用Form接收文本,统一使用multipart/form-data格式:

后端代码修改

from dotenv import load_dotenv
load_dotenv()

from fastapi import APIRouter, HTTPException, UploadFile, File, Form
import base64
import os
from ai_interaction.prompt import assemble_prompt
from ai_interaction.llm import stream_openai_response

router = APIRouter()

@router.post("/query")  
async def process_user_query(text: str = Form(None), file: UploadFile = File(None)):
    print("Received text:", text)
    print("Received file:", file)
    api_key = os.getenv("OPENAI_API_KEY")
    if not api_key:
        raise HTTPException(status_code=500, detail="API key not configured.")

    if not text and not file:
        raise HTTPException(status_code=400, detail="No text or file provided.")

    if text:
        image_url = text  # 后续可添加URL验证逻辑
    elif file:
        image_url = await process_uploaded_file(file)

    prompt = assemble_prompt(image_url)
    response = await stream_openai_response(prompt, api_key)
    return {"response": response}

async def process_uploaded_file(file: UploadFile):
    content = await file.read()
    base64_encoded = base64.b64encode(content).decode('utf-8')
    file_url = f"data:{file.content_type};base64,{base64_encoded}"
    await file.close()
    return file_url 

文本请求调用代码

import requests

url = "http://localhost:8000/api/query"
payload = {"text": "Explain the water molecule structure"}
response = requests.post(url, data=payload)
print("Status Code:", response.status_code)
print("Response Body:", response.json())

文件上传调用代码

import requests

url = "http://localhost:8000/api/query"
files = {"file": open("your_image.jpg", "rb")}
response = requests.post(url, files=files)
print("Status Code:", response.status_code)
print("Response Body:", response.json())

关键注意点

  • 只要端点包含UploadFile或File参数,FastAPI默认强制要求请求为multipart/form-data格式,此时无法用JSON传参,需用Form组合处理。
  • 调用时不要传数组格式的payload,需用单个键值对的字典。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 05:34:53