You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Next.js前端通过Fetch API传递FormData中URL字符串列表,FastAPI后端接收为空的问题排查及解决方法

Next.js前端通过Fetch API传递FormData中URL字符串列表,FastAPI后端接收为空的问题排查及解决方法

遇到这种前后端字段接收不一致的问题,我帮你一步步拆解可能的原因,再结合你提供的代码给出针对性解决办法:

一、先确认前端的FormData是否真的正确携带了urls字段

你已经在前端打印了FormData的键值对,但可以补一个更直接的验证,确保urls字段确实存在且值正确:
在前端的console.log代码块里加上:

console.log("urls字段实际值:", formData.get('urls'));

正常情况下应该输出类似"[\"https://mail.google.com/mail/u/0/#inbox\"]"的JSON字符串。如果这里输出符合预期,说明前端的FormData构建没问题,问题出在传输或后端解析环节。

二、重点排查Next.js API代理路由的中转丢失

你前端请求的/api/add_document_to_knowledge_base明显是Next.js的内置API路由(不是直接请求FastAPI),如果这个路由负责中转请求到FastAPI后端,很大概率是中转时没有完整传递FormData的所有字段

比如如果你的Next.js API路由代码是类似这样(可能你没贴出来):

// app/api/add_document_to_knowledge_base/route.js
export async function POST(request) {
  const formData = await request.formData();
  // 错误示例:手动重构FormData时漏掉了urls字段
  const newFormData = new FormData();
  formData.getAll('files').forEach(file => newFormData.append('files', file));
  if (formData.get('username')) newFormData.append('username', formData.get('username'));
  
  const response = await fetch(process.env.FASTAPI_URL + "/add_document_to_knowledge_base/", {
    method: "POST",
    body: newFormData,
  });
  const data = await response.json();
  return NextResponse.json(data);
}

这种情况下urls字段就会在中转时丢失,正确的做法是直接转发原始FormData,不要手动重构:

// 正确的中转方式
export async function POST(request) {
  const formData = await request.formData();
  // 直接把完整的FormData转发给FastAPI,不做字段筛选
  const response = await fetch(process.env.FASTAPI_URL + "/add_document_to_knowledge_base/", {
    method: "POST",
    body: formData,
  });
  const data = await response.json();
  return NextResponse.json(data);
}

三、FastAPI后端的参数解析优化

如果确认前端和中转都没问题,那可以调整后端的参数声明来兼容可能的解析异常:

  1. urls的Form参数设置默认值,避免接收为None
# 把原来的Optional[str]改成带默认值的str,确保至少拿到空数组的JSON字符串
urls: str = Form(default="[]")

这样即使前端意外没传值,也能解析出空数组,避免json.loads报错。

  1. 手动解析请求Form数据验证:
    如果自动解析有问题,可以临时在后端加一段代码,直接读取原始Form数据确认urls是否真的到达后端:
async def add_documents_to_knowledge_base(
    request: Request,
    files: List[UploadFile] = File(...),
    username: Optional[str] = Form(None),
    token: str = Depends(verify_token),
):
    # 手动解析Form数据,打印所有字段
    raw_form = await request.form()
    print("收到的所有Form字段:", list(raw_form.keys()))
    print("urls字段原始内容:", raw_form.get('urls'))
    # 原来的业务逻辑...

如果这里raw_form.get('urls')还是None,说明请求确实没携带该字段,回到前端和中转环节排查;如果有值,那就是FastAPI自动解析的小概率冲突,可以尝试调整参数顺序(比如把urls放在files前面),或者显式指定Form的别名(urls: Optional[str] = Form(None, alias="urls"))。

四、其他小概率排查点

  1. 浏览器环境干扰:用隐身模式打开页面测试,排除广告拦截、隐私插件修改请求的可能。
  2. 特殊字符影响:如果URL里有特殊字符(比如#),JSON.stringify会自动转义,理论上没问题,但可以临时用encodeURIComponent包裹JSON字符串测试(后端记得用urllib.parse.unquote解码),这属于兜底方案,优先用前面的方法。

内容来源于stack exchange

火山引擎 最新活动