【问题标题】:How can I post image and text MultipartForm on python3 and `requests`?如何在 python 和“请求”上发布图像和文本多部分表单?
【发布时间】:2018-05-08 03:15:05
【问题描述】:

我正在将代码从 NodeJS 移植到 python3。 我想发布图像二进制数据和文本。 我该怎么做 ?谢谢。

NodeJS

filePath = "xxx.jpeg"
text = "xxx"
return chakram.request("POST", "http://xxx",
     { "multipart" : [
           { "body" : fs.createReadStream(filePath),
             "Content-Type" : "image/jpeg",
             "Content-Disposition" : "name='file'; filename='" + filePath + "'"
           },
           { "body" : JSON.stringify(this.RequestData(text)),
             "Content-Type" : "application/specified-content-type-xxx"
           }
       ],
       "headers" : {
           "Authorization" : "xxx"
       }
     })

requests 的我的 Python 代码错误:

filePath = "xxx.jpeg"
text = "xxx"
headers = {
    "Authorization" : "xxx"
}

binary_data = None
with open(file_path, 'rb') as fp:
    binary_data = fp.read()

request_body = {
    "text": text,
    "type": "message",
    "from": {
        "id": "user1"
    }
}
files = {
    "file": (filePath, binary_data, 'image/jpeg'),
    "": ("", request_body, "application/specified-content-type-xxx")
}
resp = requests.post("http://xxx", files=files, headers=headers)

我收到 500 错误。

【问题讨论】:

  • 您是否尝试在标题中设置content type
  • NodeJS 代码在标头中没有内容类型。所以我认为内容类型不是必需的。

标签: python python-3.x python-requests


【解决方案1】:

python3 请求模块here 支持文件。这应该适合你。

import requests

url = "http://xxx"

# just set files to a list of tuples of (form_field_name, file_info)
multiple_files = [
        ('images', ('xxx.jpeg', open('xxx.jpeg', 'rb'), 'image/png')),
        ('images', ('bar.png', open('bar.png', 'rb'), 'image/png'))
]

text_data = {"key":"value"}
headers = {
    "Authorization" : "xxx",
    "Content-Type": "application/json"
}
r = requests.post(url, files=multiple_files, data=text_data, headers=headers)
r.text

【讨论】:

  • 谢谢。我需要指定文本的内容类型specified-content-type-xxx。你知道我该怎么做吗?我稍微修改了问题代码。
  • 应该进入标题内部。根据此处docs.python-requests.org/en/master/user/quickstart/…Using the json parameter in the request will change the Content-Type in the header to application/json. 的解释,它建议,内容类型应该放在标题中。
  • 嗯……没用。 request_body 确实是 Json 格式,但是由于 API 的关系,我需要设置“application/specified-content-type-xxx”。我在标题中设置了“application/specified-content-type-xxx”,但它也不起作用。我收到 500 错误。
  • 是响应状态还是此代码正在破坏。如果响应有 500,那么你能检查一下 response.text 中有什么消息吗?
  • 谢谢,上面写着{ "error": { "code": "ServiceError" } }
【解决方案2】:

我使用 Python3 库 urllib.request,它非常适合我。我还使用私钥和证书通过 SSL 身份验证上传文件。我将向您展示如何在 Python3 中执行此操作,以及与 cURL 命令等效的操作。

Bash版本:

#!/bin/bash

KEY="my_key.pem"
CERT="my_cert.pem"
PASSWORD="XXXXXXX"
URL="https://put_here_your_host.com"
FILE="my_file.txt" # or .pdf, .tar.gz, etc.

curl -k --cert $CERT:$PASSWORD --key $KEY $URL -X POST -H "xxx : xxx, yyy: yyy" -T $FILE

Python3版本:

import ssl
import urllib.request

# Set global
key = 'my_key.pem'
cert = 'my_cert.pem'
password = 'XXXXXXX'
url = 'https://put_here_your_host.com'
file = 'my_file.txt' # or .pdf, .tar.gz, etc.

# Security block. You can skip this block if you do not need it.
context = ssl.create_default_context()
context.load_cert_chain(cert, keyfile=key, password=password)
opener = urllib.request.build_opener(urllib.request.HTTPSHandler(context=context))
urllib.request.install_opener(opener)

# Set request with headers.
headers = {
    'xxx' : 'xxx',
    'yyy': 'yyy'
}
request = urllib.request.Request(url, headers=headers)

# Post your file.
urllib.request.urlopen(request, open(file, 'rb').read())

希望对你有帮助。

【讨论】:

    猜你喜欢
    • 2018-09-16
    • 1970-01-01
    • 2017-03-05
    • 2016-11-11
    • 1970-01-01
    • 2020-03-14
    • 2013-10-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多