Kaydet (Commit) 018d110e authored tarafından Thomas Tanner's avatar Thomas Tanner Kaydeden (comit) Tim Graham

Fixed #23911 -- Added support for buffer file uploads in the test client

üst dc2d75f4
...@@ -650,6 +650,7 @@ answer newbie questions, and generally made Django that much better: ...@@ -650,6 +650,7 @@ answer newbie questions, and generally made Django that much better:
Thomas Sorrel Thomas Sorrel
Thomas Steinacher <http://www.eggdrop.ch/> Thomas Steinacher <http://www.eggdrop.ch/>
Thomas Stromberg <tstromberg@google.com> Thomas Stromberg <tstromberg@google.com>
Thomas Tanner <tanner@gmx.net>
tibimicu@gmx.net tibimicu@gmx.net
Tim Graham <timograham@gmail.com> Tim Graham <timograham@gmail.com>
Tim Heap <tim@timheap.me> Tim Heap <tim@timheap.me>
......
...@@ -195,20 +195,25 @@ def encode_multipart(boundary, data): ...@@ -195,20 +195,25 @@ def encode_multipart(boundary, data):
def encode_file(boundary, key, file): def encode_file(boundary, key, file):
to_bytes = lambda s: force_bytes(s, settings.DEFAULT_CHARSET) to_bytes = lambda s: force_bytes(s, settings.DEFAULT_CHARSET)
filename = os.path.basename(file.name) if hasattr(file, 'name') else ''
if hasattr(file, 'content_type'): if hasattr(file, 'content_type'):
content_type = file.content_type content_type = file.content_type
elif filename:
content_type = mimetypes.guess_type(filename)[0]
else: else:
content_type = mimetypes.guess_type(file.name)[0] content_type = None
if content_type is None: if content_type is None:
content_type = 'application/octet-stream' content_type = 'application/octet-stream'
if not filename:
filename = key
return [ return [
to_bytes('--%s' % boundary), to_bytes('--%s' % boundary),
to_bytes('Content-Disposition: form-data; name="%s"; filename="%s"' to_bytes('Content-Disposition: form-data; name="%s"; filename="%s"'
% (key, os.path.basename(file.name))), % (key, filename)),
to_bytes('Content-Type: %s' % content_type), to_bytes('Content-Type: %s' % content_type),
b'', b'',
file.read() to_bytes(file.read())
] ]
......
...@@ -511,6 +511,8 @@ Tests ...@@ -511,6 +511,8 @@ Tests
:meth:`TestCase.setUpTestData() <django.test.TestCase.setUpTestData>`. Using :meth:`TestCase.setUpTestData() <django.test.TestCase.setUpTestData>`. Using
this technique can speed up the tests as compared to using ``setUp()``. this technique can speed up the tests as compared to using ``setUp()``.
* Added test client support for file uploads with file-like objects.
Validators Validators
^^^^^^^^^^ ^^^^^^^^^^
......
...@@ -238,6 +238,13 @@ Use the ``django.test.Client`` class to make requests. ...@@ -238,6 +238,13 @@ Use the ``django.test.Client`` class to make requests.
(The name ``attachment`` here is not relevant; use whatever name your (The name ``attachment`` here is not relevant; use whatever name your
file-processing code expects.) file-processing code expects.)
You may also provide any file-like object (e.g., :class:`~io.StringIO` or
:class:`~io.BytesIO`) as a file handle.
.. versionadded:: 1.8
The ability to use a file-like object was added.
Note that if you wish to use the same file handle for multiple Note that if you wish to use the same file handle for multiple
``post()`` calls then you will need to manually reset the file ``post()`` calls then you will need to manually reset the file
pointer between posts. The easiest way to do this is to pointer between posts. The easiest way to do this is to
......
...@@ -17,7 +17,7 @@ from django.test import TestCase, client ...@@ -17,7 +17,7 @@ from django.test import TestCase, client
from django.test import override_settings from django.test import override_settings
from django.utils.encoding import force_bytes from django.utils.encoding import force_bytes
from django.utils.http import urlquote from django.utils.http import urlquote
from django.utils.six import StringIO from django.utils.six import BytesIO, StringIO
from . import uploadhandler from . import uploadhandler
from .models import FileModel from .models import FileModel
...@@ -262,6 +262,34 @@ class FileUploadTests(TestCase): ...@@ -262,6 +262,34 @@ class FileUploadTests(TestCase):
self.assertLess(len(got), 256, self.assertLess(len(got), 256,
"Got a long file name (%s characters)." % len(got)) "Got a long file name (%s characters)." % len(got))
def test_file_content(self):
tdir = tempfile.gettempdir()
file = tempfile.NamedTemporaryFile
with file(suffix=".ctype_extra", dir=tdir) as no_content_type, \
file(suffix=".ctype_extra", dir=tdir) as simple_file:
no_content_type.write(b'no content')
no_content_type.seek(0)
simple_file.write(b'text content')
simple_file.seek(0)
simple_file.content_type = 'text/plain'
string_io = StringIO('string content')
bytes_io = BytesIO(b'binary content')
response = self.client.post('/echo_content/', {
'no_content_type': no_content_type,
'simple_file': simple_file,
'string': string_io,
'binary': bytes_io,
})
received = json.loads(response.content.decode('utf-8'))
self.assertEqual(received['no_content_type'], 'no content')
self.assertEqual(received['simple_file'], 'text content')
self.assertEqual(received['string'], 'string content')
self.assertEqual(received['binary'], 'binary content')
def test_content_type_extra(self): def test_content_type_extra(self):
"""Uploaded files may have content type parameters available.""" """Uploaded files may have content type parameters available."""
tdir = tempfile.gettempdir() tdir = tempfile.gettempdir()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment