我有这个
curl
:
curl -v "http://some.url" \
-X PUT \
-H "X-API-Key: API_KEY" \
-H 'Accept: application/json' \
-H 'Content-Type: multipart/form-data' \
-F "logo=@the_logo.png;type=image/png"
我正在尝试用 Python 复制这个。 到目前为止我尝试过的是:
import requests
with open("the_logo.png", "rb") as file_obj:
data = file_obj.read()
requests.put(
"http://some.url",
files={"logo": ("the_logo.png", data, "image/png")},
headers={
"X-API-Key": "API_KEY",
"Accept": "application/json",
"Content-Type": "multipart/form-data"}
但由于某种原因,上面的
curl
可以工作,而 Python 代码却不能,并且服务器会回复 422
。
如何让 Python 复制
curl
的功能?
所以,
curl -F ...
基本上是在模拟提交表单。
-F,--形式
(HTTP SMTP IMAP)对于 HTTP 协议族,这可以让curl 模拟用户按下提交按钮的填写表单。这会导致curl 根据 RFC 2388 使用 Content-Type multipart/form-data 来 POST 数据。
requests
模块在 Python 中复制此内容(请注意,您需要安装它 - 例如,pip3 install requests
):
import requests
with open("the_logo.png", "rb") as file:
file_content = file.read()
response = requests.put(
"http://localhost:8080",
files={"logo": file_content},
headers={
"X-API-Key": "API_KEY",
"Accept": "application/json"
}
)
urllib.request
模块:
import io
from urllib.request import urlopen, Request
import uuid
with open("the_logo.png", "rb") as file:
file_content = file.read()
boundary = uuid.uuid4().hex.encode("utf-8")
buffer = io.BytesIO()
buffer.write(b"--" + boundary + b"\r\n")
buffer.write(b"Content-Disposition: form-data; name=\"logo\"; filename=\"logo\"\r\n")
buffer.write(b"\r\n")
buffer.write(file_content)
buffer.write(b"\r\n")
buffer.write(b"--" + boundary + b"--\r\n")
data = buffer.getvalue()
request = Request(url="http://localhost:8080", data=data, method="PUT")
request.add_header("X-API-Key", "API_KEY")
request.add_header("Accept", "application/json")
request.add_header("Content-Length", len(data))
request.add_header("Content-Type", f"multipart/form-data; boundary={boundary.decode('utf-8')}")
with urlopen(request) as response:
response_body = response.read().decode("utf-8")
有关更完整的
urllib.request
实现,请参阅:https://pymotw.com/3/urllib.request/#uploading-files