FastAPI Web框架教程 第6章 表单和上传文件

6-1 什么是Form表单

需求场景

很多网站都支持上传文件,比如说:注册时上传头像;填写问卷时上传附件等等。

那么FastAPI是如何来解决文件上传的需求呢?

其实,这个需求不是FastAPI要解决的问题,这是很常见的一个需求,解决办法就是使用Form表单来上传文件。

Form表单其实是前端HTML语言中的一个标签语言,用来向服务端上传普通数据和文件。

Form表单介绍

示例1:Form表单的基本使用(浏览器直接打开该文件即可渲染出form表单页面)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录页面</title>
</head>
<body>

<h1>用户登录</h1>
<form action="/login" method="post">
    <p>姓名: <input type="text" name="username"></p>
    <p>密码:<input type="password" name="password"></p>
    <p><input type="submit" value="登录"></p>
</form>

</body>
</html>
  • action="/login",action用来设置服务端的接口,不设置表示朝当前页面所在URL发请求
  • method="post",methos用来设置发请求的方式,一共有两种:post和get,不设置默认是get请求
  • ,name用来设置该字段的字段名
  • , type用来设置该字段的类型,或者说input标签的类型

补充:常见的input标签类型

<input type="text">		    <!--普通文本-->
<input type="password">		<!--密码文本,密码密文现实-->  <!-- -->
<input type="date">		    <!--日期,固定日期提交格式-->
<input type="submit">		<!--提交,用来触发form表单提交数据的动作 -->
<input type="button">		<!--按钮,普通按钮,本身没有功能,但是结合js可以绑定事件 -->
<input type="reset">		<!--重置 --> 
<input type="radio">		<!--单选, -->	
<input type="checkbox">		<!--多选 -->
<input type="file">		    <!--文件,上传文件 -->
<input type="hidden">		<!--隐藏,隐藏当前输入框 -->

示例2:Form表单用来上传文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>上传头像</title>
</head>
<body>

<h1>上传头像</h1>
<form action="/login" method="post" enctype="multipart/form-data">
    <p>姓名: <input type="text" name="username"></p>
    <p>密码:<input type="password" name="password"></p>
    <p>头像:<input type="file" name="avatar"></p>
    <p><input type="submit" value="提交"></p>
</form>

</body>
</html>
  • enctype=“multipart/form-data”,上传文件比较特殊,需要使用enctype指定编码
  • ,上传文件的字段需要使用类型为file的input标签

6-2 Form表单两种编码方式

Form表单提交数据有两种请求方式,GET和POST。

当使用POST请求时,请求体数据有两种常用的编码方式,非常重要。

  • <form action="/login" method="post" enctype="application/x-www-form-urlencoded"></form>
    
  • <form action="/login" method="post" enctype="multipart/form-data"></form>
    

当请求体编码是application/x-www-form-urlencoded,此时编码方式和url中的查询参数编码格式一致,不能用来上传文件

当请求体编码是multipart/form-data时,既可以上传文件,也可以用来发送普通数据。

postman中演示如何使用 Form表单上传数据

  • 请求体编码是application/x-www-form-urlencoded

在这里插入图片描述

  • 请求体编码是multipart/form-data

在这里插入图片描述

6-3 使用Form接收表单数据

需求场景

请求体数据的编码格式除了可以JOSN,还可以是使用form表单的application/x-www-form-urlencoded和multipart/form-data

当前端使用form表单提交数据,enctype指定application/x-www-form-urlencoded,此时FastAPI该怎么解析数据呢?

FastAPI的解决方式

示例1:使用 Form() 函数来接收urlencoded编码格式的表单数据

from fastapi import FastAPI, Form

app = FastAPI()


@app.post("/login/")
def login(username: str = Form(), password: str = Form()):
    return {
        "username": username,
        "password": password
    }
  • 路径函数中的参数如果希望是表单字段,必须使用 Form(),否则会被当做查询参数和请求体参数。

  • Form()和前面介绍的 Path()Query()Body()Header()的用法基本一致,支持类型校核和转换。

  • 想要使用 Form接收表单数据,需要安装python扩展包:pip3 install python-multipart

除了使用postman也可以使用FastAPI自带的api文档请求接口

6-4 使用File上传文件

【前提】:需要提前下载第三方包:pip3 install python-multipart

示例1:使用 File()用来接收表单发送过来的文件

  • 路径函数中形参file要和表单中文件字段保持一致,且形参的类型为 bytes,值为File(),这样就可以直接将文件中二进制数据保存到形参file中,也就是直接将文件内容读取到内存中,适合小文件上传。
from fastapi import FastAPI, File


app = FastAPI()


@app.post("/upload")
def upload_file(file: bytes = File()):
    print(file)		# file中保存的就是文件的二进制数据
    # 文件内容保存在硬盘
    with open("a.txt", "wb") as f:
        f.write(file)
    return file

使用api文档发送请求,也可以使用postman发送表单请求

示例2:形参file的类型不能是str,但如果没有类型,直接使用 file=File()也可以,只不过这样需要特殊处理才能获取文件内容

from fastapi import FastAPI, File


app = FastAPI()


@app.post("/upload")
async def upload_file(file=File()):
    content = await file.read()		# 需要特殊处理才能过去文件的二进制数据
    print(content)
    return content

【重要】 对于上文件的上传需求,推荐使用示例1的方式。

【总结】只要在路径操作函数中声明了变量的类型是bytes且使用了File,则fastapi会将上传文件的内容全部去读到参数中。

6-5 使用UploadFile上传文件

【前提】:需要提前下载第三方包:pip3 install python-multipart

【需求】:对于大文件,不适合直接把文件内容一次性读取到内存中,此时推荐使用 UploadFile

示例1:使用UploadFile类型的三个属性

from fastapi import FastAPI, UploadFile

app = FastAPI()


@app.post("/upload")
def upload_file(file: UploadFile):		# UploadFile是类型,不用加括号哦
    	
    content = file.file.read()			# 可以直接使用文件的操作方法
    file.file.close()
    
    return {
        "filename": file.filename,		# filename 是文件名 如:a.txt
        "type": file.content_type,		# content_type 是文件类型 如:text/plain
        "content": content      		# file是标准的Python文件对象,可以直接使用文件的操作
    }

示例2:使用UploadFile类型的四个方法

from fastapi import FastAPI, UploadFile

app = FastAPI()


@app.post("/upload")
async def upload_file(file: UploadFile):
    
    content = await file.read()		# 异步读文件
    await file.close()			    # 异步关闭文件
    
    # await file.write()      		# 异步写文件
    # await fiel.seek(1)		    # 异步移动光标
        
    return {
        "filename": file.filename,
        "type": file.content_type,
        "content": content
    }

示例3:使用UploadFile的同时也可以是使用File

from fastapi import FastAPI, UploadFile, File

app = FastAPI()


@app.post("/upload")
def upload_file(file: UploadFile = File()):

    return {
        "filename": file.filename,
        "type": file.content_type,
    }

【总结】

  • UploadFile不会把文件内容全部加载到内存中,而是批量读取一定量的数据,边读边存硬盘,适合大文件。
  • UploadFile类型问变量有3个属性(filename、content_type、file),4个异步方法(read\write\seek\close)。

6-6 设置上传文件是可选的

示例:设置默认值是None就表示上传文件是可选的

from typing import Optional

from fastapi import FastAPI, File, UploadFile

app = FastAPI()


@app.post("/file")
def create_file(file: Optional[bytes] = File(default=None)):
    if not file:
        return {"message": "No file sent"}
    else:
        return {"file_size": len(file)}


@app.post("/uploadfile")
def create_upload_file(file: Optional[UploadFile] = None):
    if not file:
        return {"message": "No upload file sent"}
    else:
        return {"filename": file.filename}

6-7 上传多个文件

示例:上传多个文件,文件字段名可以同名也可以不同名

  • 同名字段时,也可使用 files: List[bytes] = File()
  • 不同名字段,可以直接定义多个形参即可。
  • 多文件上传,也可以使用UploadFile;也可以同时使用File和UploadFile
from typing import List

from fastapi import FastAPI, File, UploadFile

app = FastAPI()


@app.post("/files")
def create_files(files: List[bytes] = File()):
    return {"file_sizes": [len(file) for file in files]}


@app.post("/files2")
def create_files(file1: bytes = File(), file2: bytes = File()):
    return {
        "file1_size": len(file1),
        "file2_size": len(file2),
    }


@app.post("/uploadfiles")
def create_upload_files(files: List[UploadFile]):
    return {"filenames": [file.filename for file in files]}


@app.post("/uploadfile2")
def upload_file_and_file(file1: UploadFile, file2: bytes = File()):
    return {
        "file1_name": file1.filename,
        "file2_size": len(file2)
    }

6-8 同时接收表单数据和文件

  • 很多时候我们需要同时接收表单数据和上传的文件数据,此时我们可以同时使用Form和File或UploadFile

示例

import typing
from fastapi import FastAPI, Form, File, UploadFile

app = FastAPI()


@app.post("/register")
def register(
        avatar: typing.Optional[bytes] = File(default=None),
        username: str = Form(),
        password: str = Form(min_length=6, max_length=10),
        accessary: typing.Optional[UploadFile] = None
):
    return {
        "username": username,
        "password": password,
        "avatar": len(avatar) if avatar else 0,
        "accessary": accessary.filename if accessary else ""
    }

【注意】:同时使用Form和File时,File要放在Form前面。

    avatar: typing.Optional[bytes] = File(default=None),
    username: str = Form(),
    password: str = Form(min_length=6, max_length=10),
    accessary: typing.Optional[UploadFile] = None

):
return {
“username”: username,
“password”: password,
“avatar”: len(avatar) if avatar else 0,
“accessary”: accessary.filename if accessary else “”
}




【注意】:**同时使用Form和File时,File要放在Form前面。**



本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/510773.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

阿赵UE学习笔记——23、动画蒙太奇

阿赵UE学习笔记目录   大家好&#xff0c;我是阿赵。   继续学习虚幻引擎的使用方法。上一篇介绍了动画合成功能&#xff0c;这次介绍的动画蒙太奇&#xff0c;和动画合成有很多类似的东西&#xff0c;但本质上却又不同。   蒙太奇是法语“剪接”的意思。所以动画蒙太奇&…

ARM FVP平台的terminal窗口大小如何设置

当启动ARM FVP平台时&#xff0c;terminal窗口太小怎么办&#xff1f;看起来非常累眼睛&#xff0c;本博客来解决这个问题。 首先看下ARM FVP平台对Host主机的需求&#xff1a; 通过上图可知&#xff0c;UART默认使用的是xterm。因此&#xff0c;我们需要修改xterm的默认字体设…

STM32 M3内核寄存器概念

内容主要来自<<M3内核权威指南>> 汇编程序中的最低有效位&#xff08;Least Significant Bit&#xff09;。LSB是二进制数中最右边的位&#xff0c;它代表了数值中的最小单位。在汇编程序中&#xff0c;LSB通常用于表示数据的最小精度或者作为标志位。 ---------…

element-ui 修改el-form-item样式

文章目录 form结构修改el-form-item所有样式只修改label只修改content只修改input只修改button form结构 <el-form :model"formData" label-width"80px"> <el-form-item label"label1"> <el-input v-model"formData.valu…

新手如何用Postman做接口自动化测试

1、什么是自动化测试 把人对软件的测试行为转化为由机器执行测试行为的一种实践。 例如GUI自动化测试&#xff0c;模拟人去操作软件界面&#xff0c;把人从简单重复的劳动中解放出来&#xff0c;本质是用代码去测试另一段代码&#xff0c;属于一种软件开发工作&#xff0c;已…

二叉树 - 栈 - 计数 - leetcode 331. 验证二叉树的前序序列化 | 中等难度

题目 - 点击直达 leetcode 331. 验证二叉树的前序序列化 | 中等难度1. 题目详情1. 原题链接2. 基础框架 2. 解题思路1. 题目分析2. 算法原理方法1&#xff1a;栈方法2&#xff1a;计数 3. 时间复杂度 3. 代码实现方法1&#xff1a;栈方法2&#xff1a;计数 leetcode 331. 验证二…

免费Linux系统和生信宝典原创学习教程

免费Linux系统和生信宝典原创学习教程 生物信息的学习离不开Linux系统&#xff0c;不管自己写命令处理数据&#xff0c;还是使用现有的工具。Linux对我们来讲最重要的是它强大的命令行功能&#xff0c;可以快速、批量、灵活的处理数据的提取、统计和整理等耗时耗力的重复性工作…

CTF wed安全 (攻防世界)练习题

一、disabled_button 步骤一&#xff1a;进入网站发现按钮按不了 步骤二&#xff1a;按F12会查看源代码&#xff0c;会发现disabled disable属性 在HTML中&#xff0c; disabled 属性只有两个值&#xff1a;一个是不带值&#xff08;例如&#xff1a;disabled&#xff09;&…

4.2学习总结

一.java学习总结 (本次java学习总结,主要总结了抽象类和接口的一些知识,和它们之间的联系和区别) 一.抽象类 1.1定义: 抽象类主要用来抽取子类的通用特性&#xff0c;作为子类的模板&#xff0c;它不能被实例化&#xff0c;只能被用作为子类的超类。 2.概括: 有方法声明&…

【隐私计算实训营008——SCQL】

1.SCQL使用/集成最佳实践 目前SCQL只开放API供用户使用/集成 使用SCDBClient上手体验可以基于SCQL API开发封装白屏产品&#xff0c;或集成到业务链路中 1.1 部署系统 环境配置&#xff1a; 机器配置&#xff1a;CPU/MEM最低8C16G机构之间的网络互通 镜像&#xff1a;secret…

Redis实现高可用之持久化介绍

前言 在生产环境中&#xff0c;为了实现Redis的高可用性&#xff0c;可以采用持久化、主从复制、哨兵模式和 Cluster集群的方法确保数据的持久性和可靠性。这里首先介绍一下使用持久化实现服务器的高可用。 目录 一、Redis 高可用方法 1. 持久化 2. 主从复制 3. 哨兵 4.…

二轮电动自行车充电桩开源系统

文章目录 一、产品功能部分截图1.手机端&#xff08;小程序、安卓、ios&#xff09;2.PC端 二、小程序体验账号以及PC后台体验账号1.小程序体验账号2.PC后台体验账号关注公众号获取最新资讯 三、产品简介&#xff1f;1. 充电桩云平台&#xff08;含硬件充电桩&#xff09;&…

曲线降采样之道格拉斯-普克算法Douglas–Peucker

曲线降采样之道格拉斯-普克算法Douglas–Peucker 该算法的目的是&#xff0c;给定一条由线段构成的曲线&#xff0c;找到一条点数较少的相似曲线&#xff0c;来近似描述原始的曲线&#xff0c;达到降低时间、空间复杂度和平滑曲线的目的。 附赠自动驾驶学习资料和量产经验&…

【与C++的邂逅】---- 函数重载与引用

关注小庄 顿顿解馋(▿) 喜欢的小伙伴可以多多支持小庄的文章哦 &#x1f4d2; 数据结构 &#x1f4d2; C 引言 : 上一篇博客我们了解了C入门语法的一部分&#xff0c;今天我们来了解函数重载&#xff0c;引用的技术&#xff0c;请放心食用 ~ 文章目录 一. &#x1f3e0; 函数重…

windows搭建ftp实现局域网共享文件

一、开启ftp服务 1.使用 win Q 键&#xff0c;快捷打开搜索框 2.搜索框内搜索 “控制面板” 3. 进入控制面板内选择 ”程序“ 4. 单击进入 “启用或关闭windows功能” 5. 找到并展开“internet information services”、 6. 建议展开后全选 “FTP服务器” 和 “web管理工…

OpenHarmony实战:轻量系统芯片移植

本文从芯片适配的端到端视角&#xff0c;为芯片/模组制造商提供基于OpenHarmony的芯片适配指导。典型的芯片架构&#xff0c;例如cortex-m、risc-v系列都可以按照本文档进行适配移植。 约束与限制 本文档适用于OpenHarmony LTS 3.0.1及之前版本的轻量系统的适配。 说明&#…

Redis中的复制功能(三)

复制 服务器运行ID 除了复制偏移量和复制积压缓冲区之外&#xff0c;实现部分重同步还需要用到服务器运行ID(run ID): 1.每隔Redis服务器&#xff0c;不论主服务器还是从服务&#xff0c;都会有自己的运行ID2.运行ID在服务器启动时自动生成&#xff0c;由40个随机的十六进制…

ndk ffmpeg

报错&#xff1a; 解决办法&#xff1a; 报错 解决办法&#xff1a;

大模型量化技术-GPTQ

大模型量化技术-GPTQ 2022年,Frantar等人发表了论文 GPTQ:Accurate Post-Training Quantization for Generative Pre-trained Transformers。 这篇论文详细介绍了一种训练后量化算法,适用于所有通用的预训练 Transformer模型,同时只有微小的性能下降。 GPTQ算法需要通过…

vscode安装通义灵码

作为vscode的插件&#xff0c;直接使用 通义灵码-灵动指间&#xff0c;快码加编&#xff0c;你的智能编码助手 通义灵码&#xff0c;是一款基于通义大模型的智能编码辅助工具&#xff0c;提供行级/函数级实时续写、自然语言生成代码、单元测试生成、代码注释生成、代码解释、研…