如何在 Python 3 中使用“-F”复制“curl”?

问题描述 投票:0回答:2

我有这个

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
的功能?

python http curl python-requests
2个回答
0
投票

经过一些阅读后,看来技巧是在使用

Content-Type
requests
参数时在标题中设置
files


0
投票

所以,

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

© www.soinside.com 2019 - 2024. All rights reserved.