可以使用 FastAPI 提供的 File 定义客户端要上传的文件
学习 File 前最好先学习 Form:
https://www.cnblogs.com/poloyy/p/15311533.html
安装 python-multipart
要用 File,需要先安装这个库
pip install python-multipart
File 是继承 Form,所以可以定义和 Form 相同的元数据以及额外的验证
上传单个文件的栗子
# author: 小菠萝测试笔记
# blog: https://www.cnblogs.com/poloyy/
# time: 2021/9/22 9:52 上午
# file: 21_File.py
import uvicorn
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(... ) ):
result = {
"filename" : file.filename,
"content-type" : file.content_type,
"read" : await file.read()
return result
if __name__ == "__main__" :
uvicorn.run(app="21_File:app" , host="127.0.0.1" , port=8080 , reload=True , debug=True )
因为 UploadFile 对象提供的方法都是 async 异步的,所以调用的时候都要加 await 比如
await file.read()
(后面会详解 async/await )
当使用异步方法时,FastAPI 在线程池中运行文件方法并等待它们
不加 await 调用 async 方法会报错
raise ValueError(errors)
ValueError: [TypeError("'coroutine' object is not iterable"), TypeError('vars() argument must have __dict__ attribute' )]
WARNING: StatReload detected file change in '21_File.py' . Reloading...
file: bytes 的请求结果
file: UploadFile 的请求结果
查看 Swagger API 文档
这样就可以直接在 Swagger API 文档上测试上传文件功能啦
file: bytes
FastAPI 将会读取文件,接收到的内容就是文件字节
会将整个内容存储在内存中,更
适用于小文件
file: UploadFile
FastAPI 的 UploadFile 直接继承了 Starlette 的 UploadFile,但增加了一些必要的部分,使其与 Pydantic 和 FastAPI 的其他部分兼容
UploadFile 相比 bytes 的优势
存储在内存中的文件达到最大大小限制,超过此限制后,
它将存储在磁盘中
,可以很好地处理大文件,如图像、视频、大型二进制文件等,而不会消耗所有内存
可以从上传的文件中获取元数据
有一个类似文件的 async 异步接口
它公开了一个 Python SpooledTemporaryFile 对象,可以将它传递给其他需要文件的库
UploadFile 具有以下属性
filename:
str,
上传的原始文件名,例如
myimage.jpg
content_type:
str,包含 content-type(
MIME type / media type),
例如
image/jpeg
file:
一个
SpooledTemporaryFile(一个类似文件的对象)。
这是实际的
Python 文件,可以将其直接传递给其他需要
“类文件
”对象的函数或库
UploadFIle 具有以下 async 异步方法
write(data):
写入data ( str
或 bytes )
到文件
read(size):
读取文件的 size (int)
个字节/
字符
seek(offset):
转到文件中的字节位置 offset(int),如:
await myfile.seek(0)
将转到文件的开头
close():
关闭文件
上传多个文件的栗子
from typing import List
@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]}
正确传参的请求结果
查看 Swagger API 文档