diff --git a/django/http/__init__.py b/django/http/__init__.py index a67dbdc949..6de8ed4940 100644 --- a/django/http/__init__.py +++ b/django/http/__init__.py @@ -430,6 +430,8 @@ class HttpResponse(object): return sum([len(chunk) for chunk in self._container]) class HttpResponseSendFile(HttpResponse): + sendfile_fh = None + def __init__(self, path_to_file, content_type=None, block_size=8192): if not content_type: from mimetypes import guess_type @@ -445,10 +447,14 @@ class HttpResponseSendFile(HttpResponse): os.path.basename(path_to_file)) self[settings.HTTPRESPONSE_SENDFILE_HEADER] = path_to_file - def _get_content(self): - return open(self.sendfile_filename).read() + def __iter__(self): + from django.core.servers.basehttp import FileWrapper + return FileWrapper(self.get_file_handler(), self.block_size) - content = property(_get_content) + def get_file_handler(self): + if not self.sendfile_fh: + self.sendfile_fh = open(self.sendfile_filename, 'rb') + return self.sendfile_fh class HttpResponseRedirect(HttpResponse): _status_code = 302 diff --git a/tests/regressiontests/sendfile/tests.py b/tests/regressiontests/sendfile/tests.py index cdae1db60f..b28cb2ead8 100644 --- a/tests/regressiontests/sendfile/tests.py +++ b/tests/regressiontests/sendfile/tests.py @@ -25,10 +25,11 @@ class SendFileTests(TestCase): self.assertEqual(response['Content-Length'], str(FILE_SIZE)) self.assertEqual(response['Content-Type'], 'application/pdf') - # *if* the degraded case is to be supported, add this instead: - self.assertEqual(response.content, CONTENT) + # Test the fallback file transfer -- we use FileWrapper to iterate through + # the file, this also wraps close(). This appears to mitigate performance + # issues. + self.assertEqual("".join(iter(response)), CONTENT) get_content = lambda: response.content.read() - #self.assertRaises(TypeError, get_content) file1.close() # TODO: test middleware bypass etc