我有一个用于处理文件上传的 FastAPI 端点,如下所示:
@app.post('/upload')
async def accept_some_file(f: UploadFile):
content = await f.read()
# ... do stuff with content and generate a response
但这似乎只适用于
multipart/form-data
编码的有效负载。
我希望能够通过如下所示的请求直接发送文件字节:
POST /upload HTTP/1.1
Host: localhost:8080
User-Agent: curl/7.79.1
Accept: */*
Content-Type: image/jpeg
Content-Length: 11044
... image bytes
我可以使用 FastAPI 设置来允许此操作吗?或者是否有另一种请求类型对此用例更有意义?
您可以使用
bytes
获取请求正文作为 await request.body()
。如果您想以 synchronous 方式执行此操作(即,使用 def
端点 - 请参阅 here 了解 def
与 async def
),请查看 此答案。
from fastapi import Request
@app.post('/upload')
async def upload_file(request: Request):
body = await request.body()
您还可以以
stream
的形式访问请求正文,如这个答案(在“更新”部分下)和这个答案(它提供了另一个工作示例,演示如何使用接收文件和表单数据)中所述request.stream()
)。通过这种方式,无需首先将整个主体存储到内存中即可提供字节块(另请参阅 Starlette 的文档)——与使用 request.body()
相比,如上一个选项所示,这可能会导致问题,如果请求正文(例如文件)无法放入服务器的 RAM。
请注意,下面的示例将字节块存储在名为
body
的变量中(本质上是将它们存储到 RAM 中),但这仅用于演示目的。但是,如果您需要在字节块到达时将其写入磁盘,请查看上面的链接答案,了解如何使用 aiofiles
或 streaming_form_data
库执行此操作。
@app.post('/upload')
async def upload_file(request: Request):
chunks = list()
async for chunk in request.stream():
chunks.append(chunk)
body = b''.join(chunks)