fastapi_No.7_获取表单和文件数据

前面几篇主要讲解的是fastapi在接收JSON数据时,该如何进行处理。但是在Web中存在表单和文件两种类型的数据传输情况。本篇中主要针对这两种数据类型进行讲解。

表单数据

要使用表单,需预先安装python-multipart包。

# 激活虚拟环境
cd env/Scripts
activate
# 安装python-multipart包
pip install python-multipart

使用方法

要获取表单数据,就是要在路径操作函数中定义响应的变量,且该变量的默认值为Form函数的返回值。
下面是后端代码:

from random import paretovariate
from fastapi import FastAPI
# 演示获取表单数据的步骤
# 第一步:导入Form函数
from fastapi import Form
# 第二步:创建一个FastAPI类的实例对象
app = FastAPI()
# 第三步:创建一个路径装饰器
@app.post("/register")
# 第四步:创建一个路径操作函数,声明Form表单变量
async def create_user(username: str = Form(), password: str = Form()):
    return {
        "result": "register successfully",
        "username": username,
        "password": password
    }
# 第五步:运行服务器
if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app="main:app", host="127.0.0.1", port=8080, reload=True)

下面是前端测试页面代码:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>register</title>
</head>

<body>
    <h2>这是一个测试fastapi获取表单数据的页面</h2>
    <!--action路径需要和后端定义的路径匹配!!!-->
    <form action="http://127.0.0.1:8080/register" method="post">
        <label for="name">用户名:</label><input type="text" name="username" id="name"><br>
        <label for="pwd">密码:</label><input type="password" name="password" id="pwd"><br>
        <button type="submit">注册</button>
    </form>
</body>

</html>

下面是测试结果:
前端输入截图
后端响应截图

表单字段注意事项

根据HTTP协议规定一次请求体中不能具有两种编码格式。
所以在一个路径操作函数中可以声明多个Form参数,但不能同时声明要接收JSON的Body字段。这是因为Form字段的编码是application/x-www-form-urlencoded,而Body字段的编码是application/json。

文件数据

File函数方式

使用File函数方式和使用Form函数方式相同,在路径操作函数中将文件参数的默认值设定为File函数的返回值。
下面是后端的代码示例:

# 演示接收文件数据
# File方式,利用File来声明这个变量接收的是一个文件数据
from fastapi import File
@app.post("/file/file")
# 此处的...表示None,...表示省略第一个形参
# filename需要和前端的变量名一致
async def get_file(filename:bytes = File(...)):
    return {"file_size":len(filename)}

下面是前端的代码示例:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <h2>这是用来演示fastapi接收文件数据的前端演示</h2>
    <form action="http://127.0.0.1:8080/file/file" method="post" enctype="multipart/form-data">
    <!--注意此处filename必须和后端文件参数变量名一致-->
        <label for="file1"></label><input type="file" name="filename" id="file1">
        <button type="submit">上传</button>
    </form>

</body>

</html>

下面是演示结果:
前端演示结果
演示结果

UploadFile类方式

利用fastapi包中的UploadFile类,来声明变量的数据类型,以引入文件参数。
后端代码演示如下:

# 演示UploadFile类接收文件数据
# UploadFile方式,利用UploadFile来声明变量的类型
from fastapi import UploadFile
@app.post("/file/uploadfile")
async def get_uploadfile(file:UploadFile):
    # filename:上传文件名字符串(str),例如, myimage.jpg;
    # content_type:内容类型(MIME 类型 / 媒体类型)字符串(str),例如,image/jpeg;
    return{
        "filename":file.filename,
        "content_type":file.content_type
    }

前端代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <h2>这是用来演示fastapi接收文件数据的前端演示</h2>
    <!--form 中包含文件时编码格式应该是multipart/form-data-->
    <form action="http://127.0.0.1:8080/file/uploadfile" method="post" enctype="multipart/form-data">
        <label for="file">文件</label><input type="file" name="file" id="file">
        <button type="submit">上传文件</button>
    </form>
</body>

</html>

演示结果:
前端界面
演示结果

多文件数据获取

想获取多个文件数据,只需要将接收文件数据的变量类型声明为列表即可。
后端代码如下:

# 演示File和UploadFile接收多文件数据
# 接收多文件时需要将接收文件类型的参数,声明为包含文件的列表形式
from typing import List
@app.post("/files/file")
async def get_files(files:List[bytes]=File(...)):
    return {
        "file_number":len(files)
    }
    
@app.post("/files/uploadfile")
async def get_files(files:List[UploadFile]):
    filesname = [file.filename for file in files]
    return { "filesname":filesname}

前端代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Files</title>
</head>

<body>
    <h2>演示File的多文件数据引用</h2>
    <form action="http://127.0.0.1:8080/files/file" method="post" enctype="multipart/form-data">
        <label for="files">
            文件名:
        </label>
        <input type="file" name="files" id="files" multiple>
        <button type="submit">上传文件</button>
    </form>

    <h2>演示UploadFile的多文件数据引用</h2>
    <form action="http://127.0.0.1:8080/files/uploadfile" method="post" enctype="multipart/form-data">
        <label for="files">
            文件名:
        </label>
        <input type="file" name="files" id="files" multiple>
        <button type="submit">上传文件</button>
    </form>

</body>

</html>

演示结果:
File方式获取多个文件
演示结果
UploadFile方式获取多个文件
演示结果

File和UploadFile方式的优缺点

方式优点缺点
File()将文件的所有内容都存储在内存里,适用于小型文件不适合存储大文件
UploadFile使用spooled文件:存储在内存的文件超出最大上限时,fastapi会把文件存入磁盘。适合处理图像,视频,二进制等大型文件,不会占用所有内存。自带file-like async接口,可以像操作文件一样操作文件数据

表单和文件混合

有时候在一个表单中可能既包含表单数据又包含文件数据,这种情况fastapi也是支持的。只需声明各个数据所对应的数据类型即可。
需要注意的是在前端中对form的编码需设定为multipart/form-data。
后端示例代码

# 演示既接收Form数据又接收文件数据
@app.post("/mixdata")
async def get_mixdata(username=Form(),file:UploadFile=File()):
    return {
        "username":username,
        "filename":file.filename
    }

前端示例代码

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <h2>这是用来演示fastapi接收混合表单数据的前端演示</h2>
    <!--form 中包含文件时编码格式应该是multipart/form-data-->
    <form action="http://127.0.0.1:8080/mixdata" method="post" enctype="multipart/form-data">
        <label for="username">用户名:</label><input type="text" name="username" id="username"><br>
        <label for="file">文件:</label><input type="file" name="file" id="file"><br>
        <button type="submit">提交</button>
    </form>
</body>

</html>

演示结果:

前端输入
结果

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
优化一下下面的代码def FileUploads_modelform(request): """ 批量上传文件 方法三:采用modelform上传,超级简单,只需要实例化表单的时候 接收一下表单里边字符串数据文件,然后利用表单的save()方法保存一下数据即可 :param request: :return: """ # 判断提交方式GET 或POST if request.method == 'POST': File_ModelForm = FileUpload_ModelForm(request.POST, request.FILES) # 实例化FileUploadForm表单,注意获取数据的方式 if File_ModelForm.is_valid(): # file = File_ModelForm.cleaned_data['file'] # 对于文件,自动保存 # 字段+上传路径自动保存到数据库 # file_form = File_ModelForm.save() # 保存表单数据库 # 多属性保存 Upload_File = File_ModelForm.save(commit=False) # Upload_File.file_url = Upload_File.file_url.temporary_file_path() # 文件路径 # 调用get_optimized_file_type函数获取优化文件类型 # optimized_file_type = get_optimized_file_type(Upload_File.file_url) Upload_File.file_name = Upload_File.file_url.name # 文件名 Upload_File.file_size = Upload_File.file_url.size # 文件大小 Upload_File.file_update_author = request.user.realname # 获取文件类型 # Get the file content type uploaded_file_type, encoding = mimetypes.guess_type(Upload_File.file_url.path) Upload_File.file_type = uploaded_file_type # Upload_File.file_type = Upload_File.file_url.content_type # optimized_file_type = get_optimized_file_type(file_url) Upload_File.save() # 其他操作,例如返回成功页面或其他处理 # return render(request, 'zadmin/pages/File_Uploads.html', {'file_form': file_form}) return HttpResponse("文件上传成功!") else: file_form = FileUpload_ModelForm() return render(request, 'zadmin/pages/File_Uploads.html', {'file_form': file_form})
07-15
下面是优化后的代码,我主要进行了以下改进: 1. 使用适当的命名规范,将函数名从 `FileUploads_modelform` 改为 `file_upload_modelform`。 2. 移除了不必要的注释。 3. 使用更具描述性的变量名。 4. 在文件上传之前,检查用户是否已经登录,并使用 `@login_required` 装饰器进行验证。 5. 使用 `get_optimized_file_type` 函数获取文件类型,并将其保存到数据库中。 6. 通过使用 `try-except` 块来处理可能的异常情况。 7. 返回适当的 HTTP 响应。 ```python from django.shortcuts import render, HttpResponse from .forms import FileUploadModelForm from .utils import get_optimized_file_type import mimetypes @login_required def file_upload_modelform(request): if request.method == 'POST': form = FileUploadModelForm(request.POST, request.FILES) if form.is_valid(): try: uploaded_file = form.save(commit=False) uploaded_file.file_name = uploaded_file.file_url.name uploaded_file.file_size = uploaded_file.file_url.size uploaded_file.file_update_author = request.user.realname uploaded_file_type, encoding = mimetypes.guess_type(uploaded_file.file_url.path) uploaded_file.file_type = uploaded_file_type optimized_file_type = get_optimized_file_type(uploaded_file.file_url.path) uploaded_file.optimized_file_type = optimized_file_type uploaded_file.save() return HttpResponse("文件上传成功!") except Exception as e: return HttpResponse("文件上传失败:" + str(e)) else: form = FileUploadModelForm() return render(request, 'zadmin/pages/File_Uploads.html', {'form': form}) ``` 请确保在你的Django应用程序中正确导入 `FileUploadModelForm` 和 `get_optimized_file_type` 函数,并根据你的实际需求进行适当的调整。 希望这个优化后的代码对你有帮助!如果还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱学习_程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值