Loading django/core/handlers/wsgi.py +2 −0 Original line number Diff line number Diff line Loading @@ -197,6 +197,8 @@ class WSGIHandler(base.BaseHandler): for c in response.cookies.values(): response_headers.append((str('Set-Cookie'), str(c.output(header='')))) start_response(force_str(status), response_headers) if getattr(response, 'file_to_stream', None) is not None and environ.get('wsgi.file_wrapper'): response = environ['wsgi.file_wrapper'](response.file_to_stream) return response Loading django/http/__init__.py +5 −3 Original line number Diff line number Diff line from django.http.cookie import SimpleCookie, parse_cookie from django.http.request import (HttpRequest, QueryDict, RawPostDataException, UnreadablePostError, build_request_repr) from django.http.response import (HttpResponse, StreamingHttpResponse, from django.http.response import ( HttpResponse, StreamingHttpResponse, FileResponse, HttpResponseRedirect, HttpResponsePermanentRedirect, HttpResponseNotModified, HttpResponseBadRequest, HttpResponseForbidden, HttpResponseNotFound, HttpResponseNotAllowed, HttpResponseGone, HttpResponseServerError, Http404, BadHeaderError, JsonResponse) HttpResponseServerError, Http404, BadHeaderError, JsonResponse, ) from django.http.utils import fix_location_header, conditional_content_removal __all__ = [ Loading @@ -16,5 +18,5 @@ __all__ = [ 'HttpResponseBadRequest', 'HttpResponseForbidden', 'HttpResponseNotFound', 'HttpResponseNotAllowed', 'HttpResponseGone', 'HttpResponseServerError', 'Http404', 'BadHeaderError', 'fix_location_header', 'JsonResponse', 'conditional_content_removal', 'FileResponse', 'conditional_content_removal', ] django/http/response.py +19 −0 Original line number Diff line number Diff line Loading @@ -417,6 +417,9 @@ class StreamingHttpResponse(HttpResponseBase): @streaming_content.setter def streaming_content(self, value): self._set_streaming_content(value) def _set_streaming_content(self, value): # Ensure we can never iterate on "value" more than once. self._iterator = iter(value) if hasattr(value, 'close'): Loading @@ -429,6 +432,22 @@ class StreamingHttpResponse(HttpResponseBase): return b''.join(self.streaming_content) class FileResponse(StreamingHttpResponse): """ A streaming HTTP response class optimized for files. """ block_size = 4096 def _set_streaming_content(self, value): if hasattr(value, 'read'): self.file_to_stream = value filelike = value value = iter(lambda: filelike.read(self.block_size), b'') else: self.file_to_stream = None super(FileResponse, self)._set_streaming_content(value) class HttpResponseRedirectBase(HttpResponse): allowed_schemes = ['http', 'https', 'ftp'] Loading django/views/static.py +2 −3 Original line number Diff line number Diff line Loading @@ -11,7 +11,7 @@ import posixpath import re from django.http import (Http404, HttpResponse, HttpResponseRedirect, HttpResponseNotModified, StreamingHttpResponse) HttpResponseNotModified, FileResponse) from django.template import loader, Template, Context, TemplateDoesNotExist from django.utils.http import http_date, parse_http_date from django.utils.six.moves.urllib.parse import unquote Loading Loading @@ -63,8 +63,7 @@ def serve(request, path, document_root=None, show_indexes=False): return HttpResponseNotModified() content_type, encoding = mimetypes.guess_type(fullpath) content_type = content_type or 'application/octet-stream' response = StreamingHttpResponse(open(fullpath, 'rb'), content_type=content_type) response = FileResponse(open(fullpath, 'rb'), content_type=content_type) response["Last-Modified"] = http_date(statobj.st_mtime) if stat.S_ISREG(statobj.st_mode): response["Content-Length"] = statobj.st_size Loading docs/ref/request-response.txt +18 −0 Original line number Diff line number Diff line Loading @@ -998,3 +998,21 @@ Attributes .. attribute:: StreamingHttpResponse.streaming This is always ``True``. FileResponse objects ==================== .. versionadded:: 1.8 .. class:: FileResponse :class:`FileResponse` is a subclass of :class:`StreamingHttpResponse` optimized for binary files. It uses `wsgi.file_wrapper`_ if provided by the wsgi server, otherwise it streams the file out in small chunks. .. _wsgi.file_wrapper: https://www.python.org/dev/peps/pep-3333/#optional-platform-specific-file-handling ``FileResponse`` expects a file open in binary mode like so:: >>> from django.http import FileResponse >>> response = FileResponse(open('myfile.png', 'rb')) Loading
django/core/handlers/wsgi.py +2 −0 Original line number Diff line number Diff line Loading @@ -197,6 +197,8 @@ class WSGIHandler(base.BaseHandler): for c in response.cookies.values(): response_headers.append((str('Set-Cookie'), str(c.output(header='')))) start_response(force_str(status), response_headers) if getattr(response, 'file_to_stream', None) is not None and environ.get('wsgi.file_wrapper'): response = environ['wsgi.file_wrapper'](response.file_to_stream) return response Loading
django/http/__init__.py +5 −3 Original line number Diff line number Diff line from django.http.cookie import SimpleCookie, parse_cookie from django.http.request import (HttpRequest, QueryDict, RawPostDataException, UnreadablePostError, build_request_repr) from django.http.response import (HttpResponse, StreamingHttpResponse, from django.http.response import ( HttpResponse, StreamingHttpResponse, FileResponse, HttpResponseRedirect, HttpResponsePermanentRedirect, HttpResponseNotModified, HttpResponseBadRequest, HttpResponseForbidden, HttpResponseNotFound, HttpResponseNotAllowed, HttpResponseGone, HttpResponseServerError, Http404, BadHeaderError, JsonResponse) HttpResponseServerError, Http404, BadHeaderError, JsonResponse, ) from django.http.utils import fix_location_header, conditional_content_removal __all__ = [ Loading @@ -16,5 +18,5 @@ __all__ = [ 'HttpResponseBadRequest', 'HttpResponseForbidden', 'HttpResponseNotFound', 'HttpResponseNotAllowed', 'HttpResponseGone', 'HttpResponseServerError', 'Http404', 'BadHeaderError', 'fix_location_header', 'JsonResponse', 'conditional_content_removal', 'FileResponse', 'conditional_content_removal', ]
django/http/response.py +19 −0 Original line number Diff line number Diff line Loading @@ -417,6 +417,9 @@ class StreamingHttpResponse(HttpResponseBase): @streaming_content.setter def streaming_content(self, value): self._set_streaming_content(value) def _set_streaming_content(self, value): # Ensure we can never iterate on "value" more than once. self._iterator = iter(value) if hasattr(value, 'close'): Loading @@ -429,6 +432,22 @@ class StreamingHttpResponse(HttpResponseBase): return b''.join(self.streaming_content) class FileResponse(StreamingHttpResponse): """ A streaming HTTP response class optimized for files. """ block_size = 4096 def _set_streaming_content(self, value): if hasattr(value, 'read'): self.file_to_stream = value filelike = value value = iter(lambda: filelike.read(self.block_size), b'') else: self.file_to_stream = None super(FileResponse, self)._set_streaming_content(value) class HttpResponseRedirectBase(HttpResponse): allowed_schemes = ['http', 'https', 'ftp'] Loading
django/views/static.py +2 −3 Original line number Diff line number Diff line Loading @@ -11,7 +11,7 @@ import posixpath import re from django.http import (Http404, HttpResponse, HttpResponseRedirect, HttpResponseNotModified, StreamingHttpResponse) HttpResponseNotModified, FileResponse) from django.template import loader, Template, Context, TemplateDoesNotExist from django.utils.http import http_date, parse_http_date from django.utils.six.moves.urllib.parse import unquote Loading Loading @@ -63,8 +63,7 @@ def serve(request, path, document_root=None, show_indexes=False): return HttpResponseNotModified() content_type, encoding = mimetypes.guess_type(fullpath) content_type = content_type or 'application/octet-stream' response = StreamingHttpResponse(open(fullpath, 'rb'), content_type=content_type) response = FileResponse(open(fullpath, 'rb'), content_type=content_type) response["Last-Modified"] = http_date(statobj.st_mtime) if stat.S_ISREG(statobj.st_mode): response["Content-Length"] = statobj.st_size Loading
docs/ref/request-response.txt +18 −0 Original line number Diff line number Diff line Loading @@ -998,3 +998,21 @@ Attributes .. attribute:: StreamingHttpResponse.streaming This is always ``True``. FileResponse objects ==================== .. versionadded:: 1.8 .. class:: FileResponse :class:`FileResponse` is a subclass of :class:`StreamingHttpResponse` optimized for binary files. It uses `wsgi.file_wrapper`_ if provided by the wsgi server, otherwise it streams the file out in small chunks. .. _wsgi.file_wrapper: https://www.python.org/dev/peps/pep-3333/#optional-platform-specific-file-handling ``FileResponse`` expects a file open in binary mode like so:: >>> from django.http import FileResponse >>> response = FileResponse(open('myfile.png', 'rb'))