sendfile_streaming_backend.py 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. # Sendfile "streaming" backend
  2. # This is based on sendfiles builtin "simple" backend but uses a StreamingHttpResponse
  3. import os
  4. import stat
  5. from email.utils import mktime_tz, parsedate_tz
  6. from wsgiref.util import FileWrapper
  7. from django.http import HttpResponseNotModified, StreamingHttpResponse
  8. from django.utils.http import http_date
  9. def sendfile(request, filename, **kwargs):
  10. # Respect the If-Modified-Since header.
  11. statobj = os.stat(filename)
  12. if not was_modified_since(
  13. request.META.get("HTTP_IF_MODIFIED_SINCE"),
  14. statobj[stat.ST_MTIME],
  15. ):
  16. return HttpResponseNotModified()
  17. response = StreamingHttpResponse(FileWrapper(open(filename, "rb")))
  18. response["Last-Modified"] = http_date(statobj[stat.ST_MTIME])
  19. return response
  20. def was_modified_since(header=None, mtime=0):
  21. """
  22. Was something modified since the user last downloaded it?
  23. header
  24. This is the value of the If-Modified-Since header. If this is None,
  25. I'll just return True.
  26. mtime
  27. This is the modification time of the item we're talking about.
  28. """
  29. try:
  30. if header is None:
  31. raise ValueError
  32. header_date = parsedate_tz(header)
  33. if header_date is None:
  34. raise ValueError
  35. header_mtime = mktime_tz(header_date)
  36. if mtime > header_mtime:
  37. raise ValueError
  38. except (ValueError, OverflowError):
  39. return True
  40. return False