上传多个文件时FastAPI/Mangum JSON解码错误

问题描述 投票:0回答:1

我正在尝试使用 FastAPI/Mangum 创建无服务器文件上传 API,但在尝试遵循文档中的示例时遇到了奇怪的 JSON 解码问题。

这是我的代码:

# main.py
import os

from typing import List
from fastapi import FastAPI, File, UploadFile
from fastapi.responses import HTMLResponse
from mangum import Mangum

app = FastAPI()

@app.get("/")
async def main():
    content = """
    <body>
     <form action="/registration/create" enctype="multipart/form-data" method="post">
      <input name="files" type="file" multiple>
      <input type="submit">
     </form>
    </body>
    """
    return HTMLResponse(content=content)

@app.post("/registration/create")
async def create_registration(files: List[UploadFile]):
    return {"file_len": len(files)}

handler = Mangum(app)
# test_main.py
from urllib import response
from fastapi.testclient import TestClient
from main import app

client = TestClient(app)

def test_registration():
    files = [('files', ('example.txt', open('example.txt', 'rb'), 'text/plain'))]
    response = client.post("/registration/create", files=files)
    assert response.status_code == 200

当我运行测试或尝试使用网页示例访问

POST
文件时,我收到 JSON 解码错误,并且请求失败并显示
422
状态代码错误:

{
 "detail":
   [{"loc":["body",0],
     "msg":"Expecting value: line 1 column 1 (char 0)",
     "type":"value_error.jsondecode",
     "ctx": {
       "msg": "Expecting value",
       "doc": "\nContent-Disposition: form-data; name=\\"files\\"; filename=\\"example.txt\\"\\r\\nContent-Type: text/plain\\r\\n\\r\\nexample text in the file\n",
     "pos":0,
     "lineno":1,
     "colno":1
  }
 }]
}

这是我引用的docs页面。

python file-upload python-requests fastapi starlette
1个回答
0
投票

您收到的错误只是表明您的 FastAPI 端点按照定义的方式需要 JSON 数据,这是因为您没有指定

UploadFile
的类型,即使用
= File(...)
。因此,FastAPI 将
List[UploadFile]
解释为 JSON 主体。

您的端点应该如下所示:

from fastapi import File

@app.post("/registration/create")
async def create_registration(files: List[UploadFile] = File(...)):
    return {"file_len": len(files)}

请查看这个答案,以及这个这个答案以了解更多详细信息。

更新

在最新版本的FastAPI中,您可以定义类型为

UploadFile
的文件参数,而无需在参数的默认值中使用= File()
= File(...)
。因此,以下内容也应该按预期工作:

@app.post("/registration/create") async def create_registration(files: List[UploadFile]): return {"file_len": len(files)}
工作示例

此示例基于 FastAPI 的

多文件上传文档。

from fastapi import FastAPI, UploadFile from fastapi.responses import HTMLResponse from typing import List app = FastAPI() @app.post("/files/") async def create_files(files: List[UploadFile]): return {"filenames": [file.filename for file in files]} @app.get("/") async def main(): content = """ <body> <form action="/files/" enctype="multipart/form-data" method="post"> <input name="files" type="file" multiple> <input type="submit"> </form> </body> """ return HTMLResponse(content=content)
    
© www.soinside.com 2019 - 2024. All rights reserved.