首页 文章

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

提问于
浏览
135

如何在python中发送带有请求的 multipart/form-data ?如何发送文件,我明白了,但是如何通过这种方法发送表单数据无法理解 .

5 回答

  • 88

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

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

    和httpbin.org让你知道你发布的 Headers ;在 response.json() 我们有:

    >>> from pprint import pprint
    >>> pprint(response.json()['headers'])
    {u'Accept': u'*/*',
     u'Accept-Encoding': u'gzip, deflate, compress',
     u'Connection': u'close',
     u'Content-Length': u'141',
     u'Content-Type': u'multipart/form-data; boundary=33b4531a79be4b278de5f5688fab7701',
     u'Host': u'httpbin.org',
     u'User-Agent': u'python-requests/2.2.1 CPython/2.7.6 Darwin/13.2.0',
     u'X-Request-Id': u'eaf6baf8-fc3d-456b-b17d-e8219ccef1b1'}
    

    files 也可以是两值元组的列表,如果您需要订购和/或具有相同名称的多个字段:

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

    如果同时指定 filesdata ,那么它将取决于 data 的值,将用于创建POST主体 . 如果 data 是一个字符串,则只能使用它;否则使用 datafiles ,首先列出 data 中的元素 .

  • 92

    由于之前的答案已经写好,请求已经改变 . 有关更多详细信息,请查看bug thread at Github,并查看this comment .

    简而言之,files参数采用 dict ,其中键是表单字段的名称,值是字符串或2,3或4长度的元组,如请求快速入门中的POST a Multipart-Encoded File部分所述:

    >>> url = 'http://httpbin.org/post'
    >>> files = {'file': ('report.xls', open('report.xls', 'rb'), 'application/vnd.ms-excel', {'Expires': '0'})}
    

    在上面,元组组成如下:

    (filename, data, content_type, headers)
    

    如果该值只是一个字符串,则文件名将与键相同,如下所示:

    >>> files = {'obvius_session_id': '72c2b6f406cdabd578c5fd7598557c52'}
    
    Content-Disposition: form-data; name="obvius_session_id"; filename="obvius_session_id"
    Content-Type: application/octet-stream
    
    72c2b6f406cdabd578c5fd7598557c52
    

    如果值是元组并且第一个条目是 None ,则不包括filename属性:

    >>> files = {'obvius_session_id': (None, '72c2b6f406cdabd578c5fd7598557c52')}
    
    Content-Disposition: form-data; name="obvius_session_id"
    Content-Type: application/octet-stream
    
    72c2b6f406cdabd578c5fd7598557c52
    
  • 42

    即使您不需要上传任何文件,也需要使用 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-tuple3-tuple or a 4-tuple .

    基于以上所述,包含要上载的文件和表单字段的最简单的多部分表单请求如下所示:

    multipart_form_data = {
        'file2': ('custom_file_name.zip', open('myfile.zip', 'rb')),
        'action': ('', 'store'),
        'path': ('', '/path1')
    }
    
    response = requests.post('https://httpbin.org/post', files=multipart_form_data)
    
    print(response.content)
    

    ☝请注意空字符串作为纯文本字段的元组中的第一个参数 - 这是文件名字段的占位符,仅用于文件上载,但对于文本字段,仍需要空占位符才能提交数据 .


    如果此API对您来说不够pythonic,或者您需要发布多个具有相同名称的字段,请考虑使用requests toolbeltpip 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.py', 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'),
               )
        )
    
  • 3

    您需要使用站点HTML中的上载文件的 name 属性 . 例:

    autocomplete="off" name="image">
    

    你看 name="image"> ?您可以在站点的HTML中找到它以上载文件 . 您需要使用它来上传文件 Multipart/form-data

    脚本:

    import requests
    
    site = 'https://prnt.sc/upload.php' # the site where you upload the file
    filename = 'image.jpg'  # name example
    

    在此处,在图像位置,以HTML格式添加上载文件的名称

    up = {'image':(filename, open(filename, 'rb'), "multipart/form-data")}
    

    如果上传需要点击上传按钮,您可以这样使用:

    data = {
         "Button" : "Submit",
    }
    

    然后启动请求

    request = requests.post(site, files=up, data=data)
    

    完成后,文件上传成功

  • 0

    以下是您需要将一个大型单个文件作为multipart formdata上传的python代码段 . NodeJs Multer中间件在服务器端运行 .

    import requests
    latest_file = 'path/to/file'
    url = "http://httpbin.org/apiToUpload"
    files = {'fieldName': open(latest_file, 'rb')}
    r = requests.put(url, files=files)
    

    对于服务器端,请检查multer文档:https://github.com/expressjs/multer此处字段单('fieldName')用于接受单个文件,如:

    var upload = multer().single('fieldName');
    

相关问题