diff --git a/AUTHORS.rst b/AUTHORS.rst index a4b2411b..658f0b96 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -98,3 +98,4 @@ Patches and Suggestions - Shivaram Lingamneni - Miguel Turner - Rohan Jain (crodjer) +- Justin Barber diff --git a/docs/user/quickstart.rst b/docs/user/quickstart.rst index 62316309..bdb6635c 100644 --- a/docs/user/quickstart.rst +++ b/docs/user/quickstart.rst @@ -222,6 +222,34 @@ Setting filename explicitly:: "data": "" } +Sending strings to be received as files:: + + >>> url = 'http://httpbin.org/post' + >>> files = {'file': ('report.csv', 'some,data,to,send\nanother,row,to,send\n')} + + >>> r = requests.post(url, files=files) + >>> r.text + { + "origin": "179.13.100.4", + "files": { + "file": "some,data,to,send\\nanother,row,to,send\\n" + }, + "form": {}, + "url": "http://httpbin.org/post", + "args": {}, + "headers": { + "Content-Length": "216", + "Accept-Encoding": "identity, deflate, compress, gzip", + "Connection": "keep-alive", + "Accept": "*/*", + "User-Agent": "python-requests/0.11.1", + "Host": "httpbin.org", + "Content-Type": "multipart/form-data; boundary=127.0.0.1.502.41433.1335385481.788.1" + }, + "json": null, + "data": "" + } + Response Status Codes --------------------- diff --git a/requests/models.py b/requests/models.py index 1d6aa77a..4447be54 100644 --- a/requests/models.py +++ b/requests/models.py @@ -33,7 +33,7 @@ from .utils import ( DEFAULT_CA_BUNDLE_PATH) from .compat import ( cookielib, urlparse, urlunparse, urljoin, urlsplit, urlencode, str, bytes, - is_py2) + StringIO, is_py2) # Import chardet if it is available. try: @@ -349,6 +349,8 @@ class Request(object): else: fn = guess_filename(v) or k fp = v + if isinstance(fp, (bytes, str)): + fp = StringIO(fp) fields.update({k: (fn, fp.read())}) (body, content_type) = encode_multipart_formdata(fields) diff --git a/tests/test_requests.py b/tests/test_requests.py index 71967bb3..530008a3 100755 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -329,6 +329,37 @@ class RequestsTestSuite(TestSetup, TestBaseMixin, unittest.TestCase): self.assertEqual(post2.status_code, 200) + def test_POSTBIN_GET_POST_FILES_STRINGS(self): + + for service in SERVICES: + + url = service('post') + + post1 = post(url, files={'fname.txt': 'fdata'}) + self.assertEqual(post1.status_code, 200) + + post2 = post(url, files={'fname.txt': 'fdata', 'fname2.txt':'more fdata'}) + self.assertEqual(post2.status_code, 200) + + post3 = post(url, files={'fname.txt': 'fdata', 'fname2.txt':open(__file__,'rb')}) + self.assertEqual(post3.status_code, 200) + + post4 = post(url, files={'fname.txt': 'fdata'}) + self.assertEqual(post4.status_code, 200) + + post5 = post(url, files={'file': ('file.txt', 'more fdata')}) + self.assertEqual(post5.status_code, 200) + + post6 = post(url, files={'fname.txt': '\xe9'}) + self.assertEqual(post6.status_code, 200) + + post7 = post(url, files={'fname.txt': 'fdata to verify'}) + rbody = json.loads(post7.text) + self.assertTrue(rbody.get('files', None)) + self.assertTrue(rbody['files'].get('fname.txt'), None) + self.assertEqual(rbody['files']['fname.txt'], 'fdata to verify') + + def test_nonzero_evaluation(self): for service in SERVICES: