FastAPI从入门到实战(11)——表单请求与上传文件

本文主要记录表单的数据请求以及上传不同大小的文件、上传多个文件、获取文件信息等相关内容。

表单请求

@app07.post("/stu07/form")
def stu07_form(
        param1: str = Form(),
        param2: str = Form(),
        param3: int = Form()
):
    return {
    
    
        "param1": param1,
        "param2": param2,
        "param3": param3
    }

同路径参数和查询参数一致,利用fastapi内置的Form方法进行声明即可;

image-20221202182310041

上传一个bytes文件

@app07.post("/stu07/files")
def stu07_files(
        file: bytes = File()
):
    return {
    
    
        "files_size": len(file)
    }

上传文件都是以Form形式进行上传,上面代码中的File也是继承至Form;

如果把路径操作函数参数的类型声明为 bytes,FastAPI 将以 bytes 形式读取和接收文件内容。

这种方式把文件的所有内容都存储在内存里,适用于小型文件。

image-20221202182443372

使用UploadFile上传文件

@app07.post("/stu07/uploadfile/")
def stu07_uploadfile(
        file: UploadFile
):
    return {
    
    
        "文件名": file.filename,
        "内容类型": file.content_type
    }

UploadFilebytes 相比有更多优势;更适于处理图像、视频、二进制文件等大型文件,好处是不会占用所有内存;

使用UploadFile 也可以直接利用属性获取相关信息:

  • filename:上传文件名字符串(str),例如, myimage.jpg
  • content_type:内容类型(MIME 类型 / 媒体类型)字符串(str),例如,image/jpeg
  • fileSpooledTemporaryFilefile-like 对象)。其实就是 Python文件,可直接传递给其他预期 file-like 对象的函数或支持库。

UploadFile 支持以下 async 方法,(使用内部 SpooledTemporaryFile)可调用相应的文件方法。

  • write(data):把 data (str 或 bytes)写入文件;
  • read(size):按指定数量的字节或字符(size (int))读取文件内容;
  • 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()

image-20221202182630119

可选文件上传

@app07.post("/stu07/optionalfile")
def stu07_optional_file(
        file: Optional[bytes] = File(None)
):
    if not file:
        return {
    
    "message": "未上传文件"}
    else:
        return {
    
    "filesize": len(file)}

同样利用Optional或者Union进行设置即可;

image-20221202182723271

设置元数据

@app07.post("/stu07/uploadfile/metadata/")
def stu07_uploadfile_metadata(
        file: UploadFile = File(None, description="一个UploadFile文件")
):
    if not file:
        return {
    
    "message": "未上传文件"}
    else:
        return {
    
    "filename": file.filename}

这部分内容和路径参数和查询参数一致,根据需求进行设置即可;

image-20221202182807495

上传多文件

@app07.post("/stu07/fileslist")
def stu07_files_list(
        byteslist: List[bytes] = File(...),
        uploadfilelist: List[UploadFile] = File(...)
):
    return {
    
    
        "bytes_files_size": [len(file) for file in byteslist],
        "upload_filesname": [file.filename for file in uploadfilelist]
    }

上传多个文件,设置对应参数为List类型即可;

image-20221202182933070

同时上传表单参数和文件

@app07.post("/stu07/form_file/")
def stu07_form_file(
        file: UploadFile,
        form: str = Form()
):
    return {
    
    
        "filename": file.filename,
        "form": form
    }

混合上传,即在对应的路径函数中声明不同的参数即可;

image-20221202183039266

源码

# -*- coding: utf-8 -*-
# @Time: 2022/11/30 18:09
# @Author: MinChess
# @File: stu07.py
# @Software: PyCharm
from fastapi import APIRouter, Form, File, UploadFile
from typing import List, Optional
from fastapi.encoders import jsonable_encoder
from pydantic import BaseModel
from datetime import datetime

app07 = APIRouter()


# 一个form请求
@app07.post("/stu07/form")
def stu07_form(
        param1: str = Form(),
        param2: str = Form(),
        param3: int = Form()
):
    return {
    
    
        "param1": param1,
        "param2": param2,
        "param3": param3
    }


# 上传一个bytes类型的文件
@app07.post("/stu07/files")
def stu07_files(
        file: bytes = File()
):
    return {
    
    
        "files_size": len(file)
    }


# 使用UploadFile
@app07.post("/stu07/uploadfile/")
def stu07_uploadfile(
        file: UploadFile
):
    return {
    
    
        "文件名": file.filename,
        "内容类型": file.content_type
    }


# 可选文件上传
@app07.post("/stu07/optionalfile")
def stu07_optional_file(
        file: Optional[bytes] = File(None)
):
    if not file:
        return {
    
    "message": "未上传文件"}
    else:
        return {
    
    "filesize": len(file)}


# 设置UploadFile元数据
@app07.post("/stu07/uploadfile/metadata/")
def stu07_uploadfile_metadata(
        file: UploadFile = File(None, description="一个UploadFile文件")
):
    if not file:
        return {
    
    "message": "未上传文件"}
    else:
        return {
    
    "filename": file.filename}


# 多文件上传
@app07.post("/stu07/fileslist")
def stu07_files_list(
        byteslist: List[bytes] = File(...),
        uploadfilelist: List[UploadFile] = File(...)
):
    return {
    
    
        "bytes_files_size": [len(file) for file in byteslist],
        "upload_filesname": [file.filename for file in uploadfilelist]
    }


# 同时上传表单和文件
@app07.post("/stu07/form_file/")
def stu07_form_file(
        file: UploadFile,
        form: str = Form()
):
    return {
    
    
        "filename": file.filename,
        "form": form
    }


感谢阅读!

九陌斋地址:https://blog.jiumoz.com/archives/fastapi-cong-ru-men-dao-shi-zhan-biao-dan-qing-qiu-yu-shang-chuan-wen-jian

猜你喜欢

转载自blog.csdn.net/qq_45730223/article/details/128167209