不要使用字典,请使用
(key, value)元组列表作为查询参数:
params = [('title', 'file1'), ('title', 'file2'), ('title', 'file3')]否则,您将只得到一个键。
你应该 不 设置
Content-Type头;
requests使用该
files参数时将为您正确设置;这样,正确的边界也将包括在内。绝对不要自己直接设置边界:
params = [('title', 'file1'), ('title', 'file2'), ('title', 'file3')]r = requests.post('http://example.com', files=files, headers=headers, params=params)您可以通过在每个文件元组中添加第4个元素以设置额外的标题来为 每个文件部分 设置标题,但是在这种情况下,您不应该
Content-Disposition自己尝试设置标题。无论如何它都会被覆盖。
自省准备好的请求对象将为您提供:
>>> import requests>>> from pprint import pprint>>> files = {'file1': ('foo.txt', 'fooncontentsn','text/plain'), ...'file2': ('bar.txt', 'bar contents', 'text/plain'),...'file3': ('baz.txt', 'baz contents', 'text/plain')}>>> headers = {'Content-Disposition': 'attachment'}>>> params = [('title', 'file1'), ('title', 'file2'), ('title', 'file3')]>>> r = requests.Request('POST', 'http://example.com',...files=files, headers=headers, params=params)>>> prepared = r.prepare()>>> prepared.url'http://example.com/?title=file1&title=file2&title=file3'>>> pprint(dict(prepared.headers)){'Content-Disposition': 'attachment', 'Content-Length': '471', 'Content-Type': 'multipart/form-data; boundary=7312ccd96db94419bf1d97f2c54bbad1'}>>> print prepared.body--7312ccd96db94419bf1d97f2c54bbad1Content-Disposition: form-data; name="file3"; filename="baz.txt"Content-Type: text/plainbaz contents--7312ccd96db94419bf1d97f2c54bbad1Content-Disposition: form-data; name="file2"; filename="bar.txt"Content-Type: text/plainbar contents--7312ccd96db94419bf1d97f2c54bbad1Content-Disposition: form-data; name="file1"; filename="foo.txt"Content-Type: text/plainfoocontents--7312ccd96db94419bf1d97f2c54bbad1--如果绝对必须拥有
multipart/mixed,则必须
multipart/form-data自己构建POST主体并从中设置标头。随附的
urllib3工具应该能够为您做到这一点:
from requests.packages.urllib3.fields import RequestFieldfrom requests.packages.urllib3.filepost import enpre_multipart_formdatafields = [] for name, (filename, contents, mimetype) in files.items(): rf = RequestField(name=name, data=contents,filename=filename) rf.make_multipart(content_disposition='attachment', content_type=mimetype) fields.append(rf)post_body, content_type = enpre_multipart_formdata(fields)content_type = ''.join(('multipart/mixed',) + content_type.partition(';')[1:])headers = {'Content-Type': content_type}requests.post('http://example.com', data=post_body, headers=headers, params=params)或者您可以使用该
from email.mime.multipart import MIMEMultipartfrom email.mime.text import MIMETextbody = MIMEMultipart()for name, (filename, contents, mimetype) in files.items(): part = MIMEText(contents, _subtype=mimetype.partition('/')[-1], _charset='utf8') part.add_header('Content-Disposition', 'attachment', filename=filename) body.attach(part)post_body = body.as_string().partition('nn')[-1]content_type = body['content-type']headers = {'Content-Type': content_type}requests.post('http://example.com', data=post_body, headers=headers, params=params)但要考虑到此方法希望您设置一个字符集(我假设JSON和XML为UTF-8),并且很有可能使用base64编码作为内容:
>>> body = MIMEMultipart()>>> for name, (filename, contents, mimetype) in files.items():... part = MIMEText(contents, _subtype=mimetype.partition('/')[-1], _charset='utf8')... part.add_header('Content-Disposition', 'attachment', filename=filename)... body.attach(part)... >>> post_body = body.as_string().partition('nn')[-1]>>> content_type = body['content-type']>>> print post_body--===============1364782689914852112==MIME-Version: 1.0Content-Type: text/plain; charset="utf-8"Content-Transfer-Encoding: base64Content-Disposition: attachment; filename="baz.txt"YmF6IGNvbnRlbnRz--===============1364782689914852112==MIME-Version: 1.0Content-Type: text/plain; charset="utf-8"Content-Transfer-Encoding: base64Content-Disposition: attachment; filename="bar.txt"YmFyIGNvbnRlbnRz--===============1364782689914852112==MIME-Version: 1.0Content-Type: text/plain; charset="utf-8"Content-Transfer-Encoding: base64Content-Disposition: attachment; filename="foo.txt"Zm9vCmNvbnRlbnRzCg==--===============1364782689914852112==-->>> print content_typemultipart/mixed; boundary="===============1364782689914852112=="


