代码之家  ›  专栏  ›  技术社区  ›  dexi

在请求中使用“header”时,python请求会删除“data”

  •  6
  • dexi  · 技术社区  · 7 年前

    我正在使用一个站点的REST API,当我要上载文件时,该站点需要此请求类型:

    1. 标题中的“授权”和多部分内容类型
    2. 格式为二进制字符串的文件(正文)
    3. 请求URL中的文件类型

    所以我做了以下代码:

    import requests
    
    url = 'http://httpbin.org/post'
    
    parameters = {
            'format': 'pdf',
            }
    
    headers = {
      'Content-Type': 'multipart/form-data',
      'Accept': 'application/json',
      'Authorization' : 'Some authorization code'
            }
    
    data = {'file': open('1.pdf', 'rb')}
    
    r = requests.post(url, params=parameters, headers=headers, data=data)
    
    print(r.text)
    

    但似乎请求正在丢弃数据:

    {
      "args": {
        "format": "pdf"
      },
      "data": "",
      "files": {},
      "form": {},
      "headers": {
        "Accept": "application/json",
        "Accept-Encoding": "gzip, deflate",
        "Authorization": "Some authorization code",
        "Connection": "close",
        "Content-Length": "30",
        "Content-Type": "multipart/form-data",
        "Host": "httpbin.org",
        "User-Agent": "python-requests/2.18.1"
      },
      "json": null,
      "origin": "x.x.x.x",
      "url": "http://httpbin.org/post?format=pdf"
    }
    

    它起作用了 当我删除“标题”部分时 请求中:

    r = requests.post(url, params=parameters, data=data)
    

    因为响应是:

    {
      "args": {
        "format": "pdf"
      },
      "data": "",
      "files": {},
      "form": {
        "fax_file": "some samplae texts\n"
      },
      "headers": {
        "Accept": "*/*",
        "Accept-Encoding": "gzip, deflate",
        "Connection": "close",
        "Content-Length": "30",
        "Content-Type": "application/x-www-form-urlencoded",
        "Host": "httpbin.org",
        "User-Agent": "python-requests/2.18.1"
      },
      "json": null,
      "origin": "x.x.x.x",
      "url": "http://httpbin.org/post?format=pdf"
    }
    

    我也尝试了准备好的请求,结果是一样的。

    1 回复  |  直到 7 年前
        1
  •  1
  •   Martijn Pieters    5 年前

    您正在尝试发布 文件数据 ,因此使用 files 选项:

    r = requests.post(url, params=parameters, files=data, headers=headers)
    

    您真的不应该设置 Content-Type 然而,标题;当您使用 文件 选项本例中的标题包括字段边界,以便真正希望库为您处理此问题:

    headers = {
      'Accept': 'application/json',
      'Authorization' : 'Some authorization code'
    }
    

    如果保留内容类型标头,则必须提前生成内容正文,以便能够向接收服务器提供所需的边界信息。

    你可以尝试一下 Accept 标题太多;默认情况下 requests 将添加 Accept: */* 如果未指定该标头,则表示 任何东西 可接受。

    仅使用时 data 参数,参数编码为 application/x-www-form-urlencoded 表单,它不支持大型文件数据 内容类型 标题与文章正文的实际内容不匹配。

    看见 Post a Multipart-Encoded File 请求 文件和 application/x-www-form-urlencoded or multipart/form-data? 这里是堆栈溢出。

    演示:

    >>> import requests
    >>> url = 'http://httpbin.org/post'
    >>> parameters = {'format': 'pdf'}
    >>> headers = {
    ...   'Accept': 'application/json',
    ...   'Authorization' : 'Some authorization code',
    ... }
    >>> data = {'file': open('1.pdf', 'rb')}
    >>> r = requests.post(url, params=parameters, files=data, headers=headers)
    >>> print(r.text)
    {
      "args": {
        "format": "pdf"
      },
      "data": "",
      "files": {
        "file": "<file data as base64>"
      },
      "form": {},
      "headers": {
        "Accept": "application/json",
        "Accept-Encoding": "gzip, deflate",
        "Authorization": "Some authorization code",
        "Cache-Control": "max-age=0",
        "Connection": "close",
        "Content-Length": "374751",
        "Content-Type": "multipart/form-data; boundary=d4b84f8bfd464e3f97e3de584d7315fc",
        "Host": "httpbin.org",
        "O2Gw-Id": "03",
        "User-Agent": "python-requests/2.18.4",
        "X-Gateway": "wap.london.02.net"
      },
      "json": null,
      "origin": "10.120.6.78, 82.132.221.209",
      "url": "http://httpbin.org/post?format=pdf"
    }
    

    请注意 multipart/form-data; boundary=d4b84f8bfd464e3f97e3de584d7315fc 内容类型标题的值!