如何在python中发送带有请求的“ multipart / form-data”?

发布于 2021-02-02 23:20:50

如何multipart/form-data在python中发送带有请求的请求?我了解如何发送文件,但是通过这种方法如何发送表单数据尚不清楚。

关注者
0
被浏览
327
1 个回答
  • 面试哥
    面试哥 2021-02-02
    为面试而生,有面试问题,就找面试哥。

    基本上,如果你指定files参数(字典),requests则将发送multipart/form-dataPOST而不是application/x-www-form-urlencodedPOST。你不限于在该词典中使用实际文件,但是:

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

    httpbin.org可以让你知道你发布了哪些标题;在response.json()我们有:

    >>> 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'}
    

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

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

    >>> 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 如果需要排序和/或具有相同名称的多个字段,也可以是二值元组的列表:

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

    如果同时指定files和data,然后它取决于价值的data东西将被用于创建POST体。如果data是字符串,则仅使用它将;否则data,files都使用和,并data首先列出元素。

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

    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}
    )
    

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



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看