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

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

>标题中的“授权”和多部分内容类型
>在表单(正文)中作为二进制字符串文件
>文件键入请求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"
}

它在我删除请求中的’headers’部分时有效:

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

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

最佳答案 您正尝试发布文件数据,因此请使用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标头;默认情况下,如果您没有指定该标头,请求将添加Accept:* / *,表示任何内容都是可接受的.

仅使用data参数时,参数将编码为application / x-www-form-urlencoded格式,该格式不支持大型文件数据,并且您的Content-Type标头与实际的POST正文内容不匹配.

请参阅请求文档中的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"
}

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

点赞