Commit 018d110e authored by Thomas Tanner's avatar Thomas Tanner Committed by Tim Graham
Browse files

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

parent dc2d75f4
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -650,6 +650,7 @@ answer newbie questions, and generally made Django that much better:
    Thomas Sorrel
    Thomas Steinacher <http://www.eggdrop.ch/>
    Thomas Stromberg <tstromberg@google.com>
    Thomas Tanner <tanner@gmx.net>
    tibimicu@gmx.net
    Tim Graham <timograham@gmail.com>
    Tim Heap <tim@timheap.me>
+8 −3
Original line number Diff line number Diff line
@@ -195,20 +195,25 @@ def encode_multipart(boundary, data):

def encode_file(boundary, key, file):
    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'):
        content_type = file.content_type
    elif filename:
        content_type = mimetypes.guess_type(filename)[0]
    else:
        content_type = mimetypes.guess_type(file.name)[0]
        content_type = None

    if content_type is None:
        content_type = 'application/octet-stream'
    if not filename:
        filename = key
    return [
        to_bytes('--%s' % boundary),
        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),
        b'',
        file.read()
        to_bytes(file.read())
    ]


+2 −0
Original line number Diff line number Diff line
@@ -511,6 +511,8 @@ Tests
  :meth:`TestCase.setUpTestData() <django.test.TestCase.setUpTestData>`. Using
  this technique can speed up the tests as compared to using ``setUp()``.

* Added test client support for file uploads with file-like objects.

Validators
^^^^^^^^^^

+7 −0
Original line number Diff line number Diff line
@@ -238,6 +238,13 @@ Use the ``django.test.Client`` class to make requests.
        (The name ``attachment`` here is not relevant; use whatever name your
        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
        ``post()`` calls then you will need to manually reset the file
        pointer between posts. The easiest way to do this is to
+29 −1
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@ from django.test import TestCase, client
from django.test import override_settings
from django.utils.encoding import force_bytes
from django.utils.http import urlquote
from django.utils.six import StringIO
from django.utils.six import BytesIO, StringIO

from . import uploadhandler
from .models import FileModel
@@ -262,6 +262,34 @@ class FileUploadTests(TestCase):
            self.assertLess(len(got), 256,
                            "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):
        """Uploaded files may have content type parameters available."""
        tdir = tempfile.gettempdir()