python:Fastapi - 请求表单与文件
简单絮叨下,如有问题请私信
上篇文章主要唠了接口响应的一些东西,今天主要是唠Form
表单和文件处理。表单可以理解为数据采集,而文件处理就是在获得客户端的文件进行数据返回或者直接上传服务器。
fastapi
框架中提供了操作表单的Form
和处理文件的File
,其参数的方式与 Body
和 Query
一样。
表单数据
From
它接收的不是json
,而是表单字段,使用表单需要安装pip install python-multipart
(Python
的流式多部分解析器)
from fastapi import Form
from fastapi import FastAPI
app = FastAPI()
@app.post("/login/")
async def login(username: str = Form(...), password: str = Form(...)):
if password == "123456":
return {"username": username}
else:
return "密码或账号不正确..."
注释信息:
usernam
和password
是定义了Form
表单- 如果
password
不等于字符串类型的123456
,就抛出提示信息,相反就是返回用户名 - 可在一个路径操作中声明多个
Form
参数 - 表单数据的「媒体类型」编码一般为
application/x-www-form-urlencoded
启动服务:
PS E:\git_code\python-code\fastapiProject> uvicorn form_main:app --reload
请求接口:
POST http://127.0.0.1:8000/login/
请求参数:
- 所以在
postman
中的body
-选择form-data
或x-www-form-urlencoded
进行传参
KEY | VALUE |
---|---|
username | zhangsan |
password | 123456 |
请求结果:
{
"username": "zhangsan"
}
请求文件
文件上传也是以表单的形式发送的,它默认的媒体类型编码一般为 application/form-data
因为是以表单的形式发送数据,固要安装pip install python-multipart
(Python
的流式多部分解析器)
文件上传分为两种形式,首先是直接File
,其次是UploadFile
,它俩的区别就是UploadFile
是处理大数据,相反的就是适用于小型文件
from fastapi import File
from fastapi import FastAPI
from fastapi import UploadFile
app = FastAPI()
@app.post("/file/")
async def create_file(file: bytes= File(...)):
"""
直接定义`File`参数
:param file:
:return:
"""
return {"file": file}
@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile = File(...)):
"""
含 UploadFile 的 File 参数
:param file:
:return:
"""
return {"filename": file.filename}
注释信息:
file: bytes= File(…)
把路径操作函数参数的类型声明为bytes
,FastAPI
将以bytes
形式读取和接收文件内容,这里是把文件都存储在内存里,所以适用小型文件file: UploadFile = File(…)
是存储在内存的文件超出最大上限时,FastAPI
会把文件存入磁盘,适于处理图像、视频、二进制文件等大型文件,好处是不会占用所有内存file.filename
是UploadFile
下的属性,获取文件名称
启动服务:
PS E:\git_code\python-code\fastapiProject> uvicorn form_main:app --reload
请求接口:
POST http://127.0.0.1:8000/file/
POST http://127.0.0.1:8000/uploadfile/
请求参数:
- 所以在
postman
中的body
-选择form-data
进行传参。[注意
:KEY
栏输入参数并下拉选择为File
]
直接File
传参
KEY | VALUE |
---|---|
file | 选择文件 |
含UploadFile
的File
传参
KEY | VALUE |
---|---|
file | 选择文件 |
请求结果:
直接File
请求结果
{
"file": "22222"
}
含UploadFile
的File
请求结果
{
"filename": "testing.txt"
}
多文件上传
FastAPI
支持同时上传多个文件。
可用同一个「表单字段」发送含多个文件的「表单数据」。
上传多个文件时,要声明含 bytes
或 UploadFile
的列表(List
):
from typing import List
from fastapi import File
from fastapi import FastAPI
from fastapi import UploadFile
app = FastAPI()
@app.post("/files/")
async def files(files: List[bytes] = File(...)):
"""
直接定义`File`参数
:param files:
:return:
"""
return {
"file_sizes": [len(file) for file in files]
}
@app.post("/uploadfiles/")
async def upload_files(files: List[UploadFile] = File(...)):
"""
含 UploadFile 的 File 参数
:param files:
:return:
"""
return {
"filenames": [file.filename for file in files],
"content_type": [file.content_type for file in files],
"file": [file for file in files]
}
注释信息:
file: List[bytes] = File(…)
定义了一个列表,列表中的值必须是字节类型[len(file) for file in file]
是列表推导获取文件的长度files: List[UploadFile] = File(…)
定义了一个列表,列表中的值必须是UploadFile
[file.filename for file in files]
列表推导获取文件名称[file.content_type for file in files]
列表推导获取文件类型[file for file in files]
列表推导获取文件
启动服务:
PS E:\git_code\python-code\fastapiProject> uvicorn form_main:app --reload
请求接口:
POST http://127.0.0.1:8000/files/
POST http://127.0.0.1:8000/uploadfiles/
请求参数:
- 所以在
postman
中的body
-选择form-data
进行传参。[注意
:KEY
栏输入参数并下拉选择为File
]
直接File
传参
KEY | VALUE |
---|---|
files | 选择文件 |
files | 选择文件 |
含UploadFile
的File
传参
KEY | VALUE |
---|---|
files | 选择文件 |
files | 选择文件 |
请求结果:
直接File
请求结果
{
"file_sizes": [
5,
13488
]
}
含UploadFile
的File
请求结果
{
"filenames": [
"testing.txt",
"fastapi.png"
],
"content_type": [
"text/plain",
"image/png"
],
"file": [
{
"filename": "testing.txt",
"content_type": "text/plain",
"file": {
"_file": {},
"_max_size": 1048576,
"_rolled": false,
"_TemporaryFileArgs": {
"mode": "w+b",
"buffering": -1,
"suffix": null,
"prefix": null,
"encoding": null,
"newline": null,
"dir": null,
"errors": null
}
}
},
{
"filename": "fastapi.png",
"content_type": "image/png",
"file": {
"_file": {},
"_max_size": 1048576,
"_rolled": false,
"_TemporaryFileArgs": {
"mode": "w+b",
"buffering": -1,
"suffix": null,
"prefix": null,
"encoding": null,
"newline": null,
"dir": null,
"errors": null
}
}
}
]
}
请求表单与文件
FastAPI
支持同时使用 File
和 Form
定义文件和表单字段。
from fastapi import Form
from fastapi import File
from fastapi import FastAPI
from fastapi import UploadFile
app = FastAPI()
@app.post("/filesForm/")
async def form_upload_file(
file: bytes = File(...), files: UploadFile = File(...), token: str = Form(...)
):
return {
"token": token,
"file_size": len(file),
"filename": files.filename,
"content_type": files.content_type,
}
启动服务:
PS E:\git_code\python-code\fastapiProject> uvicorn form_main:app --reload
请求接口:
POST http://127.0.0.1:8000/filesForm/
请求参数:
- 所以在
postman
中的body
-选择form-data
进行传参。[注意
:KEY
栏输入参数并下拉选择为File
]
KEY | VALUE |
---|---|
file | 选择文件 |
files | 选择文件 |
token | 1234567 |
请求结果:
{
"token": "1234567",
"file_size": 5,
"filename": "弱网测试.docx",
"content_type": "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
}
注意点:
- 可在一个路径操作中声明多个
File
与Form
参数,但不能同时声明要接收JSON
的Body
字段。因为此时请求体的编码为multipart/form-data
,不是application/json
。这不是FastAPI
的问题,而是HTTP
协议的规定。
UploadFile
的属性及方法
上述段落描述了UploadFile
的使用,这个段落描述UploadFile
提供的属性和方法。
属性
file
:获取文件对象filename
:获取上传文件的名称content_type
:获取上传文件的内容类型
{
"file": {
"filename": "弱网测试.docx",
"content_type": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"file": {
"_file": {},
"_max_size": 1048576,
"_rolled": false,
"_TemporaryFileArgs": {
"mode": "w+b",
"buffering": -1,
"suffix": null,
"prefix": null,
"encoding": null,
"newline": null,
"dir": null,
"errors": null
}
}
},
"filename": "弱网测试.docx",
"content_type": "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
}
方法
write(data)
:把data
(str
或bytes
)写入文件。踩坑:在写入str
时就会抛错误,bytes
类型就不会报错,暂时还没找到解决方法。read(size)
:按自定数量的字节或字符读取文件内容。踩坑:读取数据时,针对.txt
的文件可以读出数据,针对word
类型的文件,就会抛出错误,暂时还没找到解决方法。seek(offset)
:移动至问价字节处的位置close()
:关闭文件
read
跟seek
结合使用,可多次读取已读内容:
@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile = File(...)):
"""
含 UploadFile 的 File 参数
:param file:
:return:
"""
await file.write(b"ggggggg")
await file.seek(0)
data = await file.read()
await file.close()
return data
注意点:
如果你是异步请求,必须要搭配await
使用:
data = await file.read()
return data
如果你是普通请求,就不需要搭配await
使用:
data = file.read()
return data
今天先聊到这里吧,以上总结或许能帮助到你,或许帮助不到你,但还是希望能帮助到你,如有疑问、歧义,直接私信留言会及时修正发布;非常期待你的一键 3 连【 点赞、收藏、分享 】哟,谢谢!
未完成,待续……
一直在努力,希望你也是!
微信搜索公众号:就用python