简体   繁体   English

如何通过 python 请求库将 Starlette FormData 数据结构发送到 FastAPI 端点

[英]How to send a Starlette FormData data structure to a FastAPI endpoint via python request library

My system architecture currently sends a form data blob from the frontend to the backend, both hosted on localhost on different ports.我的系统架构当前将表单数据 blob 从前端发送到后端,两者都托管在不同端口的 localhost 上。 The form data is recieved in the backend via the FastAPI library as shown.表单数据通过 FastAPI 库在后端接收,如图所示。

@app.post('/avatar/request')
async def get_avatar_request(request: Request, Authorize: AuthJWT = Depends()):
    form = await request.form()
    return run_function_in_jwt_wrapper(get_avatar_output, form, Authorize, False)

Currently, I am trying to relay the form data unmodified to another FASTApi end point from the backend using the request library, as follows:目前,我正在尝试使用请求库将未经修改的表单数据从后端中继到另一个 FASTApi 端点,如下所示:

response = requests.post(models_config["avatar_api"], data = form_data, headers = {"response-type": "blob"})

While the destination endpoint does receive the Form Data, it seemed to not have parsed the UploadFile component properly.虽然目标端点确实收到了表单数据,但它似乎没有正确解析 UploadFile 组件。 Instead of getting the corresponding starlette UploadFile data structure, I instead receive the string of the classname, as shown in this error message:我没有得到相应的starlette UploadFile数据结构,而是收到了类名的字符串,如这条错误信息所示:

FormData([('avatarFile', '<starlette.datastructures.UploadFile object at 0x7f8d25468550>'), ('avatarFileType', 'jpeg'), ('background', 'From Image'), ('voice', 'en-US-Wavenet-B'), ('transcriptKind', 'text'), ('translateToLanguage', 'No translation'), ('transcriptText', 'do')])

How should I handle this problem?我应该如何处理这个问题?

FileUpload is a python object, you'd need to serialize it somehow before using requests.post() then deserialize it before actually getting the content out of it via content = await form["upload-file"].read() . FileUpload是一个 python 对象,你需要在使用requests.post()之前以某种方式序列化它,然后在通过content = await form["upload-file"].read()实际从中获取内容之前反序列化它。 I don't think you'd want to serialize a FileUpload object though (if it is possible), rather you'd read the content of the form data and then post that.我不认为你想要序列化一个FileUpload对象(如果可能的话),而是你会阅读表单数据的内容然后发布它。

Even better, if your other FastAPI endpoint is part of the same service, you might consider just calling a function instead and avoid requests altogether (maybe use a controller function that the route function calls in case you also need this endpoint to be callable from outside the service, then just call the controller function directly avoiding the route and the need for requests).更好的是,如果您的其他 FastAPI 端点是同一服务的一部分,您可以考虑只调用一个函数并完全避免请求(可能使用路由函数调用的控制器函数,以防您还需要从外部调用该端点服务,然后直接调用控制器函数,避免路由和请求的需要)。 This way you can pass whatever you want without needing to serialize it.这样你就可以传递任何你想要的东西而无需序列化它。

If you must use requests, then I'd read the content of the form then create a new post with with that form data.如果您必须使用请求,那么我会阅读表单的内容,然后使用该表单数据创建一个新帖子。 eg例如

form = await request.form()  # starlette.datastructures.FormData
upload_file = form["upload_file"]  # starlette.datastructures.UploadFile - not used here, but just for illustrative purposes
filename = form["upload_file"].filename  # str
contents = await form["upload_file"].read()  # bytes
content_type = form["upload_file"].content_type  # str
...
data = {k: v for k, v in form.items() if k != "upload-file"} # the form data except the file
files = {"upload-file": (filename, contents, content_type)} # the file
requests.post(models_config["avatar_api"], files=files, data=data, headers = {"response-type": "blob"})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM