在请求中使用“header”时,python请求会丢弃“data”

时间:2018-04-24 07:51:40

标签: python rest post python-requests

当我想上传文件时,我正在处理需要此请求类型的网站的REST API:

  1. '授权'和标题中的多部分内容类型
  2. 以表格(正文)中的二进制字符串文件
  3. 请求网址中的文件类型
  4. 所以我做了这段代码:

    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 个答案:

答案 0 :(得分:1)

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

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

但是,你真的不应该设置Content-Type标题;当您使用files选项时,它会为您设置。在这种情况下,标题包括字段边界,真正希望库为您处理:

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

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

您也可以尝试删除Accept标题;默认情况下requests如果您未指定该标头,则会添加Accept: */*,表明任何是可接受的。

仅使用data参数时,参数编码为application/x-www-form-urlencoded形式,不支持大文件数据,并且Content-Type标头与实际POST不匹配身体内容。

请参阅requests文档中的Post a Multipart-Encoded File和Stack Overflow上的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"
}

请注意Content-Type标头的multipart/form-data; boundary=d4b84f8bfd464e3f97e3de584d7315fc值!