在不需要上传任何文件的情况下,甚至都需要使用files参数发送多部分表单POST请求。
来自原requests 来源:
def request(method, url, **kwargs):
"""Constructs and sends a :class:`Request <Request>`.
...
:param files: (optional) Dictionary of ``'name': file-like-objects``
(or ``{'name': file-tuple}``) for multipart encoding upload.
``file-tuple`` can be a 2-tuple ``('filename', fileobj)``,
3-tuple ``('filename', fileobj, 'content_type')``
or a 4-tuple ``('filename', fileobj, 'content_type', custom_headers)``,
where ``'content-type'`` is a string
defining the content type of the given file
and ``custom_headers`` a dict-like object
containing additional headers to add for the file.
相关部分为:file-tuple can be a:
-
2-tuple(文件名,文件对象)
-
3-tuple(文件名、文件对象、内容类型)
-
4-tuple(文件名、fileobj、content_type、custom_headers)。
☝ 可能不明显的是 fileobj 在处理文件时可以是或者一个实际的文件对象,OR 处理纯文本字段时的字符串。
基于以上内容,包含要上传的文件和表单字段的最简单的多部分表单请求将如下所示:
import requests
multipart_form_data = {
'upload': ('custom_file_name.zip', open('myfile.zip', 'rb')),
'action': (None, 'store'),
'path': (None, '/path1')
}
response = requests.post('https://httpbin.org/post', files=multipart_form_data)
print(response.content)
☝ 注意 None 作为纯文本字段元组中的第一个参数 - 这是文件名字段的占位符,仅用于文件上传,但对于传递 None 作为文本字段为了提交数据,第一个参数是必需的。
多个同名字段
如果您需要发布多个具有相同名称的字段,那么您可以将有效负载定义为元组列表(或元组),而不是字典:
multipart_form_data = (
('file2', ('custom_file_name.zip', open('myfile.zip', 'rb'))),
('action', (None, 'store')),
('path', (None, '/path1')),
('path', (None, '/path2')),
('path', (None, '/path3')),
)
流式请求 API
如果上述 API 对您来说不够 Pythonic,那么请考虑使用 requests toolbelt (pip install requests_toolbelt),它是 core requests 模块的扩展,它提供对文件上传流的支持以及 MultipartEncoder可以用来代替files,它还允许您将有效负载定义为字典、元组或列表。
MultipartEncoder 可用于带或不带实际上传字段的多部分请求。它必须分配给data 参数。
import requests
from requests_toolbelt.multipart.encoder import MultipartEncoder
multipart_data = MultipartEncoder(
fields={
# a file upload field
'file': ('file.zip', open('file.zip', 'rb'), 'text/plain')
# plain text fields
'field0': 'value0',
'field1': 'value1',
}
)
response = requests.post('http://httpbin.org/post', data=multipart_data,
headers={'Content-Type': multipart_data.content_type})
如果您需要发送多个同名字段,或者如果表单字段的顺序很重要,那么可以使用元组或列表来代替字典:
multipart_data = MultipartEncoder(
fields=(
('action', 'ingest'),
('item', 'spam'),
('item', 'sausage'),
('item', 'eggs'),
)
)