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

This commit is contained in:
Thomas Tanner 2014-11-29 17:41:06 +01:00 committed by Tim Graham
parent dc2d75f4d4
commit 018d110ef5
5 changed files with 47 additions and 4 deletions

View File

@ -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>

View File

@ -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())
] ]

View File

@ -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
^^^^^^^^^^ ^^^^^^^^^^

View File

@ -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

View File

@ -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):
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()