python:Fastapi - 请求表单与文件

简单絮叨下,如有问题请私信

上篇文章主要唠了接口响应的一些东西,今天主要是唠Form表单和文件处理。表单可以理解为数据采集,而文件处理就是在获得客户端的文件进行数据返回或者直接上传服务器。

fastapi框架中提供了操作表单的Form和处理文件的File,其参数的方式与 BodyQuery一样。



表单数据

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 "密码或账号不正确..."

注释信息:

  • usernampassword是定义了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-datax-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(…)把路径操作函数参数的类型声明为 bytesFastAPI 将以 bytes 形式读取和接收文件内容,这里是把文件都存储在内存里,所以适用小型文件
  • file: UploadFile = File(…)是存储在内存的文件超出最大上限时,FastAPI 会把文件存入磁盘,适于处理图像、视频、二进制文件等大型文件,好处是不会占用所有内存
  • file.filenameUploadFile下的属性,获取文件名称

启动服务:

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 选择文件

UploadFileFile传参

KEY VALUE
file 选择文件

请求结果:

直接File请求结果

{
    "file""22222"
}

UploadFileFile请求结果

{
    "filename""testing.txt"
}


多文件上传

FastAPI 支持同时上传多个文件。

可用同一个「表单字段」发送含多个文件的「表单数据」。

上传多个文件时,要声明含 bytesUploadFile 的列表(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 选择文件

UploadFileFile传参

KEY VALUE
files 选择文件
files 选择文件

请求结果:

直接File请求结果

{
    "file_sizes": [
        5,
        13488
    ]
}

UploadFileFile请求结果

{
    "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 支持同时使用 FileForm 定义文件和表单字段。

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"
}

注意点:

  • 可在一个路径操作中声明多个 FileForm 参数,但不能同时声明要接收 JSONBody 字段。因为此时请求体的编码为 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):把datastrbytes)写入文件。踩坑:在写入str时就会抛错误,bytes类型就不会报错,暂时还没找到解决方法。
  • read(size):按自定数量的字节或字符读取文件内容。踩坑:读取数据时,针对.txt的文件可以读出数据,针对word类型的文件,就会抛出错误,暂时还没找到解决方法。
  • seek(offset):移动至问价字节处的位置
  • close():关闭文件

readseek结合使用,可多次读取已读内容:

@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

posted @ 2022-02-28 17:59  一名小测试  阅读(660)  评论(0编辑  收藏  举报