POST 使用 Python 带有文件和查询参数的请求向 FastAPI 请求
POST request to FastAPI using Python Requests with a file and query parameters
我正在使用 FastAPI 为一些 ML 模型提供服务,我有一个 Streamlit
基本 UI 使用 Python Requests
模块。
我的一项服务是通过 POST 请求获取图像,效果非常好。
服务器端
@app.post("/segformer")
async def segformer(file: Optional[UploadFile] = None):
由 {BASE_URI}/docs
给出的卷曲
curl -X 'POST' \
'http://localhost:8080/segformer' \
-H 'accept: application/json' \
-H 'Content-Type: multipart/form-data' \
-F 'file=@image1.jpg;type=image/jpeg'
客户端使用 Python 请求
response = requests.post(f"{BASE_URI}/segformer", files=files)
一旦我想添加额外的参数,它就会变得令人毛骨悚然。例如:
服务器端
@dataclass
class ModelInterface:
model_name: str = "detr"
tags: List[str] = Query(...)
@app.post("/detr")
async def detr(file: UploadFile = File(...), model: ModelInterface = Depends()):
curl -- 由 {BASE_URI}/docs
给出
curl -X 'POST' \
'http://localhost:8080/detr?model_name=detr&tags=balloon&tags=dog' \
-H 'accept: application/json' \
-H 'Content-Type: multipart/form-data' \
-F 'file=@image1.jpg;type=image/jpeg'
到那时一切正常。一旦我想使用 Python Requests
转换该调用,我就会遇到一些问题,这些问题总是以 /detr HTTP/1.1" 400 Bad Request
错误告终。
这是我试过的:
客户端使用 Python 请求
headers = {
"Content-type": "multipart/form-data",
"accept": "application/json"
}
payload = {
"tags": ["balloon", "dog"]
}
response = requests.post(
f"{BASE_URI}/detr",
headers=headers,
json=payload, <- also *data*
files=files,
)
最后似乎问题缩小了如何转换这个:
curl -X 'POST' \
'http://localhost:8080/detr?tags=balloon&tags=dog' \
-H 'accept: application/json' \
-H 'Content-Type: multipart/form-data' \
-F 'file=@image1.jpg;type=image/jpeg'
一个有效的 Python Requests
调用!
我还遇到了以下 FastAPI 代码的问题:
@dataclass
class ModelInterface:
model_name: str = "detr"
tags: List[str] = None
@app.post("/detr2")
async def detr2(file: UploadFile = File(...), model: ModelInterface = Form(...)):
...
转换为这个 curl
命令:
curl -X 'POST' \
'http://localhost:8080/detr2' \
-H 'accept: application/json' \
-H 'Content-Type: multipart/form-data' \
-F 'file=@image1.jpg;type=image/jpeg' \
-F 'model={
"model_name": "detr",
"tags": [
"balloon", "dog"
]
}'
失败并出现 "POST /detr2 HTTP/1.1" 422 Unprocessable Entity
错误
要在 Python 请求中传递查询参数,您应该改用 params
键。因此:
response = requests.post(url='<your_url_here>', params=payload)
此外,无需在 header 中设置 Content-type
,因为它会根据您传递给 requests.post()
的参数自动添加。这样做,请求将失败,因为除了 multipart/form-data
,Content-type
必须 包括使用的 boundary
值描述 post body 中的部分。不设置 Content-Type
header 确保请求将其设置为正确的值 " (ref). Have a look at this and this。此外,请确保在 files
中使用与在端点中提供的相同 key
名称,即 file
。因此,在 Python 请求中它应该看起来像像下面这样:
files = {('file', open('my_file.txt', 'rb'))}
response = requests.post(url='<your_url_here>', files=files, params=payload)
您还可以在 this answer.
找到更多关于如何将附加数据与文件一起发送的选项
我正在使用 FastAPI 为一些 ML 模型提供服务,我有一个 Streamlit
基本 UI 使用 Python Requests
模块。
我的一项服务是通过 POST 请求获取图像,效果非常好。
服务器端
@app.post("/segformer")
async def segformer(file: Optional[UploadFile] = None):
由 {BASE_URI}/docs
给出的卷曲curl -X 'POST' \
'http://localhost:8080/segformer' \
-H 'accept: application/json' \
-H 'Content-Type: multipart/form-data' \
-F 'file=@image1.jpg;type=image/jpeg'
客户端使用 Python 请求
response = requests.post(f"{BASE_URI}/segformer", files=files)
一旦我想添加额外的参数,它就会变得令人毛骨悚然。例如:
服务器端
@dataclass
class ModelInterface:
model_name: str = "detr"
tags: List[str] = Query(...)
@app.post("/detr")
async def detr(file: UploadFile = File(...), model: ModelInterface = Depends()):
curl -- 由 {BASE_URI}/docs
给出curl -X 'POST' \
'http://localhost:8080/detr?model_name=detr&tags=balloon&tags=dog' \
-H 'accept: application/json' \
-H 'Content-Type: multipart/form-data' \
-F 'file=@image1.jpg;type=image/jpeg'
到那时一切正常。一旦我想使用 Python Requests
转换该调用,我就会遇到一些问题,这些问题总是以 /detr HTTP/1.1" 400 Bad Request
错误告终。
这是我试过的:
客户端使用 Python 请求
headers = {
"Content-type": "multipart/form-data",
"accept": "application/json"
}
payload = {
"tags": ["balloon", "dog"]
}
response = requests.post(
f"{BASE_URI}/detr",
headers=headers,
json=payload, <- also *data*
files=files,
)
最后似乎问题缩小了如何转换这个:
curl -X 'POST' \
'http://localhost:8080/detr?tags=balloon&tags=dog' \
-H 'accept: application/json' \
-H 'Content-Type: multipart/form-data' \
-F 'file=@image1.jpg;type=image/jpeg'
一个有效的 Python Requests
调用!
我还遇到了以下 FastAPI 代码的问题:
@dataclass
class ModelInterface:
model_name: str = "detr"
tags: List[str] = None
@app.post("/detr2")
async def detr2(file: UploadFile = File(...), model: ModelInterface = Form(...)):
...
转换为这个 curl
命令:
curl -X 'POST' \
'http://localhost:8080/detr2' \
-H 'accept: application/json' \
-H 'Content-Type: multipart/form-data' \
-F 'file=@image1.jpg;type=image/jpeg' \
-F 'model={
"model_name": "detr",
"tags": [
"balloon", "dog"
]
}'
失败并出现 "POST /detr2 HTTP/1.1" 422 Unprocessable Entity
错误
要在 Python 请求中传递查询参数,您应该改用 params
键。因此:
response = requests.post(url='<your_url_here>', params=payload)
此外,无需在 header 中设置 Content-type
,因为它会根据您传递给 requests.post()
的参数自动添加。这样做,请求将失败,因为除了 multipart/form-data
,Content-type
必须 包括使用的 boundary
值描述 post body 中的部分。不设置 Content-Type
header 确保请求将其设置为正确的值 " (ref). Have a look at this and this。此外,请确保在 files
中使用与在端点中提供的相同 key
名称,即 file
。因此,在 Python 请求中它应该看起来像像下面这样:
files = {('file', open('my_file.txt', 'rb'))}
response = requests.post(url='<your_url_here>', files=files, params=payload)
您还可以在 this answer.
找到更多关于如何将附加数据与文件一起发送的选项