Python POST multipart/form-data 请求 Postman 的不同行为
Python POST multipart/form-data request different behavior from Postman
我正在尝试使用此 API 端点上传文件:
https://h.app.wdesk.com/s/cerebral-docs/?python#uploadfileusingpost
有了这个python函数:
def upload_file(token, filepath, table_id):
url = "https://h.app.wdesk.com/s/wdata/prep/api/v1/file"
headers = {
'Accept': 'application/json',
'Authorization': f'Bearer {token}'
}
files = {
"tableId": (None, table_id),
"file": open(filepath, "rb")
}
resp = requests.post(url, headers=headers, files=files)
print(resp.request.headers)
return resp.json()
Content-Type
和 Content-Length
header 由请求库根据其文档在内部计算和添加。在 post
函数中分配给 files
kwarg 时,库知道它应该是一个 multipart/form-data
请求。
请求 header 的打印输出如下,显示了库添加的 Content-Type
和 Content-Length
。我省略了授权令牌。
{'User-Agent': 'python-requests/2.24.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive',
'Authorization': 'Bearer <omitted>', 'Content-Length': '8201', 'Content-Type': 'multipart/form-data; boundary=bb582b9071574462d44c4b43ec4d7bf3'}
来自 API 的 json 响应是:
{'body': ['contentType must not be null'], 'code': 400}
奇怪的是,同样的请求,当通过 Postman 发出时,给出了不同的响应 - 这也是我对 Python 的期望。
{ "code": 409, "body": "duplicate file name" }
这些是 Postman 请求 headers:
POST /s/wdata/prep/api/v1/file HTTP/1.1
Authorization: Bearer <omitted>
Accept: */*
Cache-Control: no-cache
Postman-Token: 34ed08d4-4467-4168-a4e4-c83b16ce9afb
Host: h.app.wdesk.com
Content-Type: multipart/form-data; boundary=--------------------------179907322036790253179546
Content-Length: 8279
Postman 请求在发送请求时也会计算 Content-Type
和 Content-Length
header,并且不是用户指定的。
我很困惑为什么我从 API 服务中获得了针对同一请求的两种不同行为。
一定有什么东西我遗漏了,想不通是什么。
与 NodeJS 和 Postman 相比,找出我的请求有什么问题。
API 的错误消息中提到的 contentType
是文件参数的内容类型,而不是 http 请求 header Content-Type
.
当我像这样更新我的文件参数时,上传开始正常工作:
files = {
"tableId": (None, table_id),
"file": (Path(filepath).name, open(filepath, "rb"), "text/csv", None)
}
我了解到 Python 的请求库不会自动将文件的 MIME 类型添加到请求 body。我们需要明确说明。
希望这对其他人也有帮助。
我正在尝试使用此 API 端点上传文件:
https://h.app.wdesk.com/s/cerebral-docs/?python#uploadfileusingpost
有了这个python函数:
def upload_file(token, filepath, table_id):
url = "https://h.app.wdesk.com/s/wdata/prep/api/v1/file"
headers = {
'Accept': 'application/json',
'Authorization': f'Bearer {token}'
}
files = {
"tableId": (None, table_id),
"file": open(filepath, "rb")
}
resp = requests.post(url, headers=headers, files=files)
print(resp.request.headers)
return resp.json()
Content-Type
和 Content-Length
header 由请求库根据其文档在内部计算和添加。在 post
函数中分配给 files
kwarg 时,库知道它应该是一个 multipart/form-data
请求。
请求 header 的打印输出如下,显示了库添加的 Content-Type
和 Content-Length
。我省略了授权令牌。
{'User-Agent': 'python-requests/2.24.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive',
'Authorization': 'Bearer <omitted>', 'Content-Length': '8201', 'Content-Type': 'multipart/form-data; boundary=bb582b9071574462d44c4b43ec4d7bf3'}
来自 API 的 json 响应是:
{'body': ['contentType must not be null'], 'code': 400}
奇怪的是,同样的请求,当通过 Postman 发出时,给出了不同的响应 - 这也是我对 Python 的期望。
{ "code": 409, "body": "duplicate file name" }
这些是 Postman 请求 headers:
POST /s/wdata/prep/api/v1/file HTTP/1.1
Authorization: Bearer <omitted>
Accept: */*
Cache-Control: no-cache
Postman-Token: 34ed08d4-4467-4168-a4e4-c83b16ce9afb
Host: h.app.wdesk.com
Content-Type: multipart/form-data; boundary=--------------------------179907322036790253179546
Content-Length: 8279
Postman 请求在发送请求时也会计算 Content-Type
和 Content-Length
header,并且不是用户指定的。
我很困惑为什么我从 API 服务中获得了针对同一请求的两种不同行为。 一定有什么东西我遗漏了,想不通是什么。
与 NodeJS 和 Postman 相比,找出我的请求有什么问题。
API 的错误消息中提到的 contentType
是文件参数的内容类型,而不是 http 请求 header Content-Type
.
当我像这样更新我的文件参数时,上传开始正常工作:
files = {
"tableId": (None, table_id),
"file": (Path(filepath).name, open(filepath, "rb"), "text/csv", None)
}
我了解到 Python 的请求库不会自动将文件的 MIME 类型添加到请求 body。我们需要明确说明。
希望这对其他人也有帮助。