在本文中,我记录了我对API的文件上传的HTTP限制的研究以及如何克服相同的研究。
假设您想更新您的社交资料以保留您的工作电子邮件和新的个人资料图片。因此,要求包含两个数据条目:电子邮件和个人资料图片。为了确保此更新请求成功,请求标题内容类型必须反映要发送的数据的类型
什么是内容类型,为什么重要?
内容类型是我们传达要发送的数据的方式。这允许接收器进行适当的解释,可以是客户端或服务器。
- 内容类型 multipart/form-data :表达通过HTML表单提交的值。带有多部分/form-data的样品HTML形式
<form action="/" method="post" enctype="multipart/form-data">
<input type="email" name="email" value="enter your email address" />
<input type="file" name="picture" />
<button type="submit">Submit</button>
</form>
- 内容类型 application/json :表达通过JSON(JavaScript对象符号)数据提交的值。这基本上是密钥和值对的映射器。
由于内容类型允许接收器理解要发送的数据的种类,因此要进行成功的通信,因此必须尊重规则。如果接收者期望通过 suptrart/form-data 发送数据,但最终以 application/json 的形式接收数据,则通信和反之亦然。
以下是尊重应用程序/JSON内容类型的数据的示例:
{
"email": "johndoe@mail.com",
"picture": "myfile.png"
}
虽然上述数据是有效的JSON,但那里存在误解。尽管我们的目的是提交文件,但给出的图片有效载荷的价值将被解释为字符串。
那么您如何解决这个问题?
可接受的JSON有效载荷带有文件字段
虽然您无法将原始文件数据馈送到JSON对象,但您可以将原始文件转换为JSON可以理解和允许的数据。我说转换了吗?是的,我做到了。这将保证您也将数据重新将数据重新为接收方的初始状态。 JSON可以理解Base64,以下是Wikipedia的一些摘录
与所有二进制编码方案共有的共有,base64旨在携带以二进制格式存储的数据,这些数据仅可靠地支持文本内容。 base64在万维网中尤为普遍,其中
one of its uses is the ability to embed image files or other binary assets inside textual assets
(例如html和css文件)。
The more typical use is to encode binary data (such as an image)
;生成的base64数据仅包含64个不同的ASCII字符,所有这些字符都可以可靠地转移到可能破坏原始源字节的系统中。
这是上述exerpt的摘要:
base64通常用于编码二进制数据(图像,文件,e.t.c)将其理解并可以使用的文本字符串(实际上字母)。
我们该怎么做?你会问的。我会给你一个实用的答案。为了澄清到目前为止所说的所有内容,这里有一些直接的问题和快速答案
我什么时候应该使用内容类型格式多部分/form-data?从HTML表单处理请求时,请使用Multipart/form-data。
我什么时候应该使用内容类型格式应用程序/JSON?构建API(应用程序编程接口)时。
让我们回答一个大问题,我如何使用实际示例上传额外有效载荷的文件数据
如何使用Pydantic模型处理文件上传
如果您遵循了FastApi文档,它将专用一个部分来解释how to request file,您还必须安装了python-multipart
软件包,这是一项要求,因为给出的示例是从HTML表单中提出的示例,即Multipart/form-data < /em>内容类型。
但这不是我们想要的,我们希望像 application/json 内容类型一起发送数据。以下是显示正确的方法
的步骤- 将文件转换为base64数据URL字符串:我们将使用在线工具实现此目的。在研究期间,我尝试了base64guru。转换文件后,生成的字符串应具有这种格式
data:@file/jpeg;base64,/9j/4AAQSkxxxxxxxxxxxxxxxx
按原样复制发电机的响应,并将其用于步骤2
-
将值分配给图片有效载荷
-
在接收器侧,将base64数据URL字符串重新转换为初始状态
我假设您已经设置了FastAPI应用程序,因此请使用电子邮件和图片字段创建一个新的Pydantic模型
from pydantic import BaseModel, EmailStr
class UpdateProfileSchema(BaseModel):
"""Models updatable field of a profile instance"""
email:EmailStr
picture:bytes
创建一个API端点,以处理期望电子邮件和图片数据有效载荷的真实配置文件更新。此端点将接收到的base64数据URL字符串重新转换回文件,然后将文件保存在文件系统中。对于其他情况,您可能需要将文件上传到私有S3存储桶中。
import base64
@app.post("/upload", response_model=dict)
def update_profile(payload:UpdateProfileSchema):
data_split = payload.image.split('base64,')
encoded_data = data_split[1]
data = base64.b64decode(encoded_data)
with open("uploaded_image.png", "wb") as writer:
writer.write(data)
return {"detail": "Profile update successful"}
以下是我的请求有效载荷和请求标头中使用的内容类型的剪切屏幕。
结论
我们已经成功地使用 application/json 内容类型上传了一个文件。采用的分辨率不是对FastAPI的限制,而是HTTP的限制。因此,随后的方法是如何将图像/文件上传到API,而不管使用哪种框架。
遇到任何错误?在评论部分留下一个问题。如果您喜欢这篇文章,跟着我进行更多。
Want me to write for you ?
给我发送电子邮件