我有API,它接受JSON数据和文件(png
)。
这是我的fastapi代码:
@app.post("/api/")
async def dummy_file_return(metadata=Body(...),file=File(...)):
print("content_type is")
print(file.content_type)
字符串
使用curl
访问时。
$curl -X POST -F file=@0_for_django_testcase.png -F metadata='{"meta":"test"}' localhost:8008/api/
型
服务器日志显示,
content_type是
image/png
我可以看到content_type
是自动猜测的,image/png
是设置的。
然后,我用python
的requests
做了同样的事情。
response = requests.post(
url,
data={"metadata":json.dumps({"meta":"test")},
files = {
"file": open('0_for_django_testcase.png','rb')
},
)
型
控制台显示
content_type是content_type
是空的,什么也没有出现。
为什么会出现这种差异?
无论哪种方式,文件上传都成功,但content_type不同。
我没有为curl
设置任何头,-F
标志偷偷发送一些头?
在另一个试验中,我用头测试了这些模式,但都返回<Response [400]>
错误。
response = requests.post(
url,
data={"metadata":json.dumps({"meta":"test")},
files = {
"file": open('0_for_django_testcase.png','rb')
},
headers={
"Content-Type":"image/png"
}
)
response = requests.post(
url,
data={"metadata":json.dumps({"meta":"test")},
files = {
"file": open('0_for_django_testcase.png','rb')
},
headers={
"Content-Type":"multipart/form-data"
}
)
型
任何帮助感激不尽。
1条答案
按热度按时间yb3bgrhw1#
首先,我建议看看this answer,它提供了如何在FastAPI中上传文件的详细信息。其次,您似乎没有沿着发送
JSON
数据,而是发送Form
数据。在requests
中使用data
参数时就是这种情况,无论在FastAPI端点中使用Body()
定义参数,以及使用json.dumps()
序列化metadata
键的值。您还需要将请求的Content-Type
设置为application/json
,或者直接使用json
参数(参见here,以及here和here)。然而,由于您尝试同时发送文件和JSON数据,因此它不起作用-请查看this answer,了解为什么您的方法不起作用,以及如何实现。因此,您提供的示例之所以有效,是因为您将Form
数据沿着发送,这对于multipart/form-data
内容类型是有效的(有关如何使用Python请求发送multipart/form-data
,请参阅here)。至于文件的
content_type
(在本例中更好地称为 media type,以前称为 MIME type,参见MDN的文档here和here),这与requests
模块有关。(注意,有一个内置的Python模块,称为mimetypes
,它提供了类似的功能-示例在this answer的最后一节中提供)。然而,在requests
中,您可以在发送请求时手动为files
设置content_type
-请参阅此处和此处的相关文档(查看files
参数)了解更多细节,以及this answer。如果您想避免这种情况,可以使用httpx
,它会自动为您设置content_type
,如果您愿意,仍然允许您以类似于requests
的方式手动更改它,如本文所述(在FastAPI中使用httpx
的相关文章可能也有帮助,可以在here和here中找到)。下面提供了这两个选项。工作示例
app.py
字符串
test.py(使用
requests
)型
test.py(使用
httpx
)型