如何发送“多部分/表单数据"在 python 中请求? [英] How to send a "multipart/form-data" with requests in python?

查看:24
本文介绍了如何发送“多部分/表单数据"在 python 中请求?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在python中发送带有requestsmultipart/form-data?怎么发送文件,我明白了,但是这个方法怎么发送表单数据就看不懂了.

解决方案

基本上,如果你指定一个 files 参数(一个字典),那么 requests 将发送一个 multipart/form-data POST 而不是 application/x-www-form-urlencoded POST.但是,您不仅限于使用该字典中的实际文件:

<预><代码>>>>进口请求>>>response = requests.post('http://httpbin.org/post', files=dict(foo='bar'))>>>response.status_code200

和 httpbin.org 让您知道您发布的标题;在 response.json() 中,我们有:

<预><代码>>>>从 pprint 导入 pprint>>>pprint(response.json()['headers']){'接受': '*/*','接受编码':'gzip,放气','连接':'关闭','内容长度':'141','内容类型':'多部分/表单数据;''边界=c7cbfdd911b4e720f1dd8f479c50bc7f','Host': 'httpbin.org','用户代理':'python-requests/2.21.0'}

更好的是,您可以通过使用元组而不是单个字符串或字节对象来进一步控制每个部分的文件名、内容类型和其他标题.元组预计包含 2 到 4 个元素;文件名、内容、可选的内容类型和可选的其他标题字典.

我将使用带有 None 的元组形式作为文件名,以便从这些部分的请求中删除 filename="..." 参数:

<预><代码>>>>文件 = {'foo': 'bar'}>>>打印(requests.Request('POST', 'http://httpbin.org/post', files=files).prepare().body.decode('utf8'))--bb3f05a247b43eede27a124ef8b968c5内容配置:表单数据;名称=foo";文件名=foo"酒吧--bb3f05a247b43eede27a124ef8b968c5-->>>文件 = {'foo': (None, 'bar')}>>>打印(requests.Request('POST', 'http://httpbin.org/post', files=files).prepare().body.decode('utf8'))--d5ca8c90a869c5ae31f70fa3ddb23c76内容配置:表单数据;名称=富"酒吧--d5ca8c90a869c5ae31f70fa3ddb23c76--

files 也可以是一个二值元组列表,如果你需要排序和/或多个同名字段:

requests.post('http://requestb.in/xucj9exu',文件=(('foo', (None, 'bar')),('foo', (None, 'baz')),('垃圾邮件', (无, '鸡蛋')),))

如果同时指定filesdata,则取决于datavalue 是什么用于创建 POST 正文.如果 data 是字符串,则只使用它;否则同时使用 datafiles,首先列出 data 中的元素.

还有优秀的 requests-toolbelt 项目,其中包括 高级多部分支持.它采用与 files 参数相同格式的字段定义,但与 requests 不同的是,它默认不设置文件名参数.此外,它可以从打开的文件对象流式传输请求,其中 requests 将首先在内存中构造请求体:

from requests_toolbelt.multipart.encoder import MultipartEncodermp_encoder = MultipartEncoder(字段={'foo': '酒吧',# 纯文件对象,没有文件名或 MIME 类型产生# Content-Disposition 标题,只有部分名称'垃圾邮件': ('spam.txt', open('spam.txt', 'rb'), 'text/plain'),})r = 请求.post('http://httpbin.org/post',data=mp_encoder, # MultipartEncoder 作为数据发布,不要使用 files=...!# MultipartEncoder 提供具有边界的内容类型标头:headers={'Content-Type': mp_encoder.content_type})

字段遵循相同的约定;使用包含 2 到 4 个元素的元组来添加文件名、部分 mime 类型或额外的标题.与 files 参数不同,如果您不使用元组,则不会尝试查找默认的 filename 值.

How to send a multipart/form-data with requests in python? How to send a file, I understand, but how to send the form data by this method can not understand.

解决方案

Basically, if you specify a files parameter (a dictionary), then requests will send a multipart/form-data POST instead of a application/x-www-form-urlencoded POST. You are not limited to using actual files in that dictionary, however:

>>> import requests
>>> response = requests.post('http://httpbin.org/post', files=dict(foo='bar'))
>>> response.status_code
200

and httpbin.org lets you know what headers you posted with; in response.json() we have:

>>> from pprint import pprint
>>> pprint(response.json()['headers'])
{'Accept': '*/*',
 'Accept-Encoding': 'gzip, deflate',
 'Connection': 'close',
 'Content-Length': '141',
 'Content-Type': 'multipart/form-data; '
                 'boundary=c7cbfdd911b4e720f1dd8f479c50bc7f',
 'Host': 'httpbin.org',
 'User-Agent': 'python-requests/2.21.0'}

Better still, you can further control the filename, content type and additional headers for each part by using a tuple instead of a single string or bytes object. The tuple is expected to contain between 2 and 4 elements; the filename, the content, optionally a content type, and an optional dictionary of further headers.

I'd use the tuple form with None as the filename, so that the filename="..." parameter is dropped from the request for those parts:

>>> files = {'foo': 'bar'}
>>> print(requests.Request('POST', 'http://httpbin.org/post', files=files).prepare().body.decode('utf8'))
--bb3f05a247b43eede27a124ef8b968c5
Content-Disposition: form-data; name="foo"; filename="foo"

bar
--bb3f05a247b43eede27a124ef8b968c5--
>>> files = {'foo': (None, 'bar')}
>>> print(requests.Request('POST', 'http://httpbin.org/post', files=files).prepare().body.decode('utf8'))
--d5ca8c90a869c5ae31f70fa3ddb23c76
Content-Disposition: form-data; name="foo"

bar
--d5ca8c90a869c5ae31f70fa3ddb23c76--

files can also be a list of two-value tuples, if you need ordering and/or multiple fields with the same name:

requests.post(
    'http://requestb.in/xucj9exu',
    files=(
        ('foo', (None, 'bar')),
        ('foo', (None, 'baz')),
        ('spam', (None, 'eggs')),
    )
)

If you specify both files and data, then it depends on the value of data what will be used to create the POST body. If data is a string, only it willl be used; otherwise both data and files are used, with the elements in data listed first.

There is also the excellent requests-toolbelt project, which includes advanced Multipart support. It takes field definitions in the same format as the files parameter, but unlike requests, it defaults to not setting a filename parameter. In addition, it can stream the request from open file objects, where requests will first construct the request body in memory:

from requests_toolbelt.multipart.encoder import MultipartEncoder

mp_encoder = MultipartEncoder(
    fields={
        'foo': 'bar',
        # plain file object, no filename or mime type produces a
        # Content-Disposition header with just the part name
        'spam': ('spam.txt', open('spam.txt', 'rb'), 'text/plain'),
    }
)
r = requests.post(
    'http://httpbin.org/post',
    data=mp_encoder,  # The MultipartEncoder is posted as data, don't use files=...!
    # The MultipartEncoder provides the content-type header with the boundary:
    headers={'Content-Type': mp_encoder.content_type}
)

Fields follow the same conventions; use a tuple with between 2 and 4 elements to add a filename, part mime-type or extra headers. Unlike the files parameter, no attempt is made to find a default filename value if you don't use a tuple.

这篇关于如何发送“多部分/表单数据"在 python 中请求?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆