FastAPI:如何在不使用多部分/表单数据请求的情况下上传文件?

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

我有一个用于处理文件上传的 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 设置来允许此操作吗?或者是否有另一种请求类型对此用例更有意义?

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

选项1

您可以使用

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()

选项2

您还可以以

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)
© www.soinside.com 2019 - 2024. All rights reserved.