cca...@bcc190cf-cafb-0310-a4f2-bffc1f526a37  committed 294bd99

[soc2009/http-wsgi-improvements] HttpResponseSendFile now uses django.core.servers.basehttp.FileWrapper inside __iter__ to provide fallback.

regressiontests.sendfile uses this now, and passes. The fallback was tested
using guppy and apache2 with mod_wsgi for heap issues, and it appears to be
fine. We can go back and look at this again if it becomes an issue.

  • Participants
  • Parent commits b225034
  • Branches soc2009/http-wsgi-improvements

Comments (0)

Files changed (2)

File django/http/

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

File tests/regressiontests/sendfile/

         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:
-        #self.assertRaises(TypeError, get_content)
         # TODO: test middleware bypass etc