17.FastAPI 表单数据
如果接收的数据不是JSON格式,而是表单字段,则需要使用Form。在FastAPI中,要使用Form,需要事先安装python-multipart,执行如下命令:
pip install python-multipart
Form参数与Path、Query、Body一样,从fastapi导入。其使用方法相同。
from fastapi import FastAPI
from fastapi import Form
app=FastAPI()
@app.post(path='/login')
async def login(uacc: str=Form(...), upwd: str=Form(...)):
res=False
if uacc=='admin' and upwd=='admin':
res=True
return {'res': res}
执行请求:
curl -d "uacc=admin&upwd=123" -X POST 127.0.0.1:8000/login
{"res":false}
curl -d "uacc=admin&upwd=admin" -X POST 127.0.0.1:8000/login
{"res":true}
在使用Form参数时,需要注意:可以在一个路由操作中声明多个 Form 参数,但不能同时声明要接收 JSON 的 Body 字段。因为此时请求体的编码是
application/x-www-form-urlencoded,不是 application/json;这不是 FastAPI 的问题,而是 HTTP 协议的规定。
在web开发中,文件上传的需求是肯定会出现的,FastAPI通过多种方式支持文件上传操作。首先可以使用与Form、Body等相同的File,File直接继承自Form类。代码如下:
from fastapi import FastAPI
from fastapi import File
app=FastAPI()
@app.post(path='/upload')
async def login(file: bytes=File(...)):
with open('test.png', 'wb') as f:
f.write(file)
return {'file_size': len(file)}
执行请求:
curl -F "file=@demo.png" -X POST 127.0.0.1:8000/upload
{"file_size":10731}
通过查看项目所在文件夹,其下的test.png文件与demo.png文件相同。
在FastAPI中,声明文件体必须使用 File,否则,FastAPI 会把该参数当作查询参数或请求体(JSON)参数;文件作为表单数据上传;如果路由操作函数参数的类型声明为 bytes,FastAPI 将以 bytes 形式读取和接收文件内容,这种方式把文件的所有内容都存储在内存里,适用于小文件。所以,在大多数情况下,我们会使用 UploadFile。
定义 File 参数时使用 UploadFile 类型,UploadFile 的属性如下:
filename:上传文件的文件名字符串;content_type:内容类型(MIME 类型 / 媒体类型)字符串(str),如:image/jpeg;file: 文件,可直接传递给其他file对象的函数或支持库。
UploadFile 支持以下 async 方法:
write(data):把 data (str 或 bytes)写入文件;read(size):按指定数量的字节或字符(size (int))读取文件内容;seek(offset):移动至文件 offset (int)字节处的位置;例如,await myfile.seek(0) 移动到文件开头;执行 await myfile.read() 后,需再次读取已读取内容时,这种方法特别好用;close():关闭文件。
因为上述方法都是 async 方法,要搭配 await 使用。
代码如下:
from fastapi import FastAPI
from fastapi import File
from fastapi import UploadFile
app=FastAPI()
@app.post(path='/upload')
async def login(file: UploadFile=File(...)):
with open('test.png', 'wb') as f:
f.write(await file.read())
return {'file_name': file.filename}
执行请求:
curl -F "file=@demo.png" -X POST 127.0.0.1:8000/upload
{"file_name":"demo.png"}
通过查看项目所在文件夹,其下的test.png文件与demo.png文件相同。
使用UploadFile与 bytes 相比,其优势:
使用 spooled 文件:存储在内存的文件超出最大上限时,FastAPI 会把文件存入磁盘;这种方式更适于处理图像、视频、二进制文件等大型文件,好处是不会占用所有内存;可获取上传文件的元数据;自带 file-like async 接口;暴露的 Python SpooledTemporaryFile 对象,可直接传递给其他预期「file-like」对象的库。
FastAPI支持同时上传多个文件,可以使用一个表单字段上传多个文件,此时,路由操作函数要声明为包含bytes或UploadFile的列表。代码如下:
from fastapi import FastAPI
from fastapi import File
from fastapi import UploadFile
from typing import List
app=FastAPI()
@app.post(path='/upload')
async def upload(files: List[bytes]=File(...)):
sizes=[len(file) for file in files]
index=0
for file in files:
with open("{0}.png".format(index), 'wb') as f:
f.write(file)
index +=1
return sizes
@app.post(path='/upload_file')
async def upload_file(files: List[UploadFile]=File(...)):
names=[file.filename for file in files]
for file in files:
with open(file.filename, 'wb') as f:
f.write(await file.read())
return names
在FastAPI中,支持同时使用表单和文件。但可以在一个路径操作中声明 File 和 Form 参数,但不能同时声明要接收 JSON 的 Body 字段。因为此时请求体的编码是 multipart/form-data,不是 application/json。
from fastapi import FastAPI
from fastapi import Form
from fastapi import File
from fastapi import UploadFile
from typing import List
app=FastAPI()
@app.post(path='/upload')
async def upload(files: List[bytes]=File(...), desc: str=Form(...)):
print(desc)
sizes=[len(file) for file in files]
index=0
for file in files:
with open("{0}.png".format(index), 'wb') as f:
f.write(file)
index +=1
return sizes
@app.post(path='/upload_file')
async def upload_file(files: List[UploadFile]=File(...), desc: str=Form(...)):
print(desc)
names=[file.filename for file in files]
for file in files:
with open(file.filename, 'wb') as f:
f.write(await file.read())
return names
执行请求:
curl -F "desc=images" -F "files=@demo.png" -F "files=@elephant.png" -X POST 127.0.0.1:8000/upload
[10731,50279]
curl -F "desc=images" -F "files=@demo.png" -F "files=@elephant.png" -X POST 127.0.0.1:8000/upload_file
["demo.png","elephant.png"]
后台print输出:
images
INFO: 127.0.0.1:52608 - "POST /upload HTTP/1.1" 200 OK
images
INFO: 127.0.0.1:52611 - "POST /upload_file HTTP/1.1" 200 OK
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了