客户端也可以上传文件到Fastapi,只需要指定File格式即可。
解释
同Form一样,想要接收上传的文件,需要先安装python-multipart.安装命令:
pip install python-multipart.
原因
这是因为上传的文件会被解析为 "form data".
一、导入 File
从fastapi中导入 File 和 UploadFile:
from fastapi import FastAPI, File, UploadFile
二、定义 File 参数
创建文件参数:
from fastapi import FastAPI, File, UploadFile
app = FastAPI()
@app.post("/files/")
async def create_file(
file: bytes = File(...)
):
return {"file_size": len(file)}
解释
File 是直接继承自Form类的子类.
申明File请求体,你必须使用File,因为如果不使用该类,将会被解释为查询参数或者是请求体参数。
文件类型会被上传为 "form"数据类型.
如果你申明路由视图函数参数类型为bytes,FastAPI将会把文件转化为bytes类型。
File类型的内容是将内容保存在内存中的,比较适合小型文件。
下面是使用UploadFile几种情况、
三、File 参数使用 UploadFile类型
将File参数定义为UploadFile类型:
from fastapi import FastAPI, File, UploadFile
app = FastAPI()
@app.post("/files/")
async def create_file(
file: bytes = File(...)
):
return {"file_size": len(file)}
@app.post("/uploadfile/")
async def create_upload_file(
file: UploadFile = File(...)
):
return {"filename": file.filename}
文件使用UploadFile类型比bytes的几种好处:
-
UploadFile文件使用脱机文件:- 文件存储在内存中有一个最大限制,如果超过了这个界限,会保存在硬盘中
- 这意味着
UploadFile将会对大文件,比如图片、视频、大二进制文件等,不会很快消耗掉所有内存 - 可以从上传的文件中得到元数据】
-
UploadFile有 file-likeasync交互. - 它公开了一个实际的Python [
SpooledTemporaryFile](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile)对象,您可以将其直接传递给需要类似文件对象的其他库。
3.1. UploadFile
3.1.1 UploadFile 的属性:
-
filename: 具有上载原始文件名的str(例.myimage.jpg). -
content_type:content type的字符串 (MIME type / media type) (例.image/jpeg). -
file:SpooledTemporaryFile(a file-like object). 这是实际的Python文件,您可以将其直接传递给需要“类文件”对象的其他函数或库。
3.1.2 UploadFile 的 async 方法:
其实都是下面调用相应的文件方法(使用内部的'SpooledTemporaryFile`)。
-
write(data): 写data(strorbytes) 到文件. -
read(size): 读size(int) bytes/characters 文件. -
seek(offset): 文件指针定位到文件中的字节offset(int)位置- 例.,
await myfile.seek(0)文件将会定位到文件开始. - 如果您一次运行
await myfile.read()然后需要再次读取内容,则此功能特别有用。
- 例.,
-
close(): 关闭文件句柄
正如所有的方法都是async,您需要使用await调用上面的方法。
例如,
例如,在async路径操作函数中,您可以通过以下方式获取内容:
contents = await myfile.read()
如果您在常规的def路径操作功能中,则可以直接访问UploadFile.file,例如:
contents = myfile.file.read()
async 技术细节
当您使用async方法时,FastAPI在线程池中运行文件方法并等待它们。
Starlette技术细节
FastAPI的UploadFile继承自Starlette的
UploadFile,但是增加了一些必要的部分以使其与pydantic **和FastAPI的其他部分兼容。
四、"Form Data"?
HTML表单(<form> </ form>)将数据发送到服务器的方式通常对该数据使用“特殊”编码,这与JSON不同。
FastAPI将确保从正确的位置而不是JSON读取数据。
技术细节
如果表单中的数据不包含文件,则通常使用“媒体类型”
application / x-www-form-urlencoded编码。但是当表单包含文件时,它将被编码为
multipart / form-data。 如果使用File,** FastAPI **将知道它必须从主体的正确部位获取文件。
如果您想了解更多有关这些编码和表单字段的信息,请转到MDN web docs for POST.
警告⚠️
您可以在路径操作中声明多个File和Form参数,但是您也不能声明希望以JSON形式接收的Body字段,因为请求的主体将使用multipart/form-data,而不是application/json。
这并不是FastAPI的限制,而是HTTP协议的一部分。
五、多个文件上传
如果需要一次性上传多个文件,需要定义为bytes或UploadFile的List形式
from typing import List
from fastapi import FastAPI, File, UploadFile
from starlette.responses import HTMLResponse
app = FastAPI()
@app.post("/files/")
async def create_files(
files: List[bytes] = File(...)
):
return {"file_sizes": [len(file) for file in files]}
@app.post("/uploadfiles/")
async def create_upload_files(
files: List[UploadFile] = File(...)
):
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>
<form action="/uploadfiles/" enctype="multipart/form-data" method="post">
<input name="files" type="file" multiple>
<input type="submit">
</form>
</body>
"""
return HTMLResponse(content=content)
你将会得到bytes或UploadFile的列表。
注意
请注意,自2019年4月14日起,Swagger UI不支持在同一表单字段中上传多个文件。 有关更多信息,请检查#4276 和#3641。
尽管如此,FastAPI已经使用标准OpenAPI与之兼容。
因此,只要Swagger UI支持多文件上传或任何其他支持OpenAPI的工具,它们都将与FastAPI兼容。












网友评论