diff --git a/django/core/files/base.py b/django/core/files/base.py
index 71de5ab..6e92a20 100644
a
|
b
|
|
1 | 1 | from __future__ import unicode_literals |
2 | 2 | |
3 | 3 | import os |
4 | | from io import BytesIO, StringIO, UnsupportedOperation |
| 4 | from io import BytesIO, UnsupportedOperation |
5 | 5 | |
6 | 6 | from django.utils.encoding import smart_text |
7 | 7 | from django.core.files.utils import FileProxyMixin |
8 | 8 | from django.utils import six |
9 | | from django.utils.encoding import python_2_unicode_compatible |
| 9 | from django.utils.encoding import force_bytes, python_2_unicode_compatible |
10 | 10 | |
11 | 11 | @python_2_unicode_compatible |
12 | 12 | class File(FileProxyMixin): |
… |
… |
class ContentFile(File):
|
134 | 134 | A File-like object that takes just raw content, rather than an actual file. |
135 | 135 | """ |
136 | 136 | def __init__(self, content, name=None): |
137 | | content = content or b'' |
138 | | stream_class = StringIO if isinstance(content, six.text_type) else BytesIO |
139 | | super(ContentFile, self).__init__(stream_class(content), name=name) |
| 137 | super(ContentFile, self).__init__(BytesIO(force_bytes(content)), name=name) |
140 | 138 | self.size = len(content) |
141 | 139 | |
142 | 140 | def __str__(self): |
diff --git a/tests/regressiontests/file_storage/tests.py b/tests/regressiontests/file_storage/tests.py
index 595b65d..738e4f8 100644
a
|
b
|
class InconsistentGetImageDimensionsBug(unittest.TestCase):
|
560 | 560 | |
561 | 561 | class ContentFileTestCase(unittest.TestCase): |
562 | 562 | |
| 563 | def setUp(self): |
| 564 | self.storage_dir = tempfile.mkdtemp() |
| 565 | self.storage = FileSystemStorage(self.storage_dir) |
| 566 | |
| 567 | def tearDown(self): |
| 568 | shutil.rmtree(self.storage_dir) |
| 569 | |
563 | 570 | def test_content_file_default_name(self): |
564 | 571 | self.assertEqual(ContentFile(b"content").name, None) |
565 | 572 | |
… |
… |
class ContentFileTestCase(unittest.TestCase):
|
573 | 580 | def test_content_file_input_type(self): |
574 | 581 | """ |
575 | 582 | Test that ContentFile can accept both bytes and unicode and that the |
576 | | retrieved content is of the same type. |
| 583 | retrieved content is always bytes. |
577 | 584 | """ |
578 | 585 | self.assertTrue(isinstance(ContentFile(b"content").read(), bytes)) |
579 | | self.assertTrue(isinstance(ContentFile("español").read(), six.text_type)) |
| 586 | self.assertTrue(isinstance(ContentFile("español").read(), bytes)) |
| 587 | |
| 588 | def test_content_saving(self): |
| 589 | """ |
| 590 | Test that ContentFile can be saved correctly with the filesystem storage, |
| 591 | both if it was initialized with string or unicode content""" |
| 592 | self.storage.save('bytes.txt', ContentFile(b"content")) |
| 593 | self.storage.save('unicode.txt', ContentFile("español")) |
| 594 | |
580 | 595 | |
581 | 596 | class NoNameFileTestCase(unittest.TestCase): |
582 | 597 | """ |