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

dex*_*exi 5 python rest post python-requests

当我想上传文件时,我正在处理需要此请求类型的站点的 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)
Run Code Online (Sandbox Code Playgroud)

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

{
  "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"
}
Run Code Online (Sandbox Code Playgroud)

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

r = requests.post(url, params=parameters, data=data)
Run Code Online (Sandbox Code Playgroud)

因为响应是:

{
  "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"
}
Run Code Online (Sandbox Code Playgroud)

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

Mar*_*ers 1

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

\n\n
r = requests.post(url, params=parameters, files=data, headers=headers)\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n
headers = {\n  \'Accept\': \'application/json\',\n  \'Authorization\' : \'Some authorization code\'\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n

您也可以尝试删除Accept标头;如果您不指定该标头,默认情况下requests将添加,表示任何内容Accept: */*都是可以接受的。

\n\n

仅使用data参数时,参数会被编码为application/x-www-form-urlencodedform,不支持大文件数据,并且您的Content-Type标头与实际的 POST 正文内容不匹配。

\n\n

请参阅在文档和application/x-www-form-urlencoded 或 multipart/form-data 中发布多部分编码文件requests在 Stack Overflow 上。

\n\n

演示:

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

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

\n