forked from orbit-oss/flask
Added support for conditional responses to send_file
This commit is contained in:
parent
88d9315d19
commit
d0c6ad7d28
3 changed files with 36 additions and 5 deletions
2
CHANGES
2
CHANGES
|
|
@ -17,6 +17,8 @@ Codename to be decided, release date to be announced.
|
||||||
``autoescape`` tag.
|
``autoescape`` tag.
|
||||||
- refactored Flask internally. It now consists of more than a
|
- refactored Flask internally. It now consists of more than a
|
||||||
single file.
|
single file.
|
||||||
|
- :func:`flask.send_file` now emits etags and has the ability to
|
||||||
|
do conditional responses builtin.
|
||||||
|
|
||||||
Version 0.4
|
Version 0.4
|
||||||
-----------
|
-----------
|
||||||
|
|
|
||||||
|
|
@ -328,7 +328,7 @@ class Flask(_PackageBoundObject):
|
||||||
return PackageLoader(self.import_name)
|
return PackageLoader(self.import_name)
|
||||||
|
|
||||||
def init_jinja_globals(self):
|
def init_jinja_globals(self):
|
||||||
"""Callde directly after the environment was created to inject
|
"""Called directly after the environment was created to inject
|
||||||
some defaults (like `url_for`, `get_flashed_messages` and the
|
some defaults (like `url_for`, `get_flashed_messages` and the
|
||||||
`tojson` filter.
|
`tojson` filter.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import mimetypes
|
import mimetypes
|
||||||
|
from time import time
|
||||||
|
from zlib import adler32
|
||||||
|
|
||||||
# try to load the best simplejson implementation available. If JSON
|
# try to load the best simplejson implementation available. If JSON
|
||||||
# is not installed, we add a failing class.
|
# is not installed, we add a failing class.
|
||||||
|
|
@ -24,7 +26,7 @@ except ImportError:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
json_available = False
|
json_available = False
|
||||||
|
|
||||||
from werkzeug import Headers, wrap_file
|
from werkzeug import Headers, wrap_file, is_resource_modified
|
||||||
|
|
||||||
from flask.globals import session, _request_ctx_stack, current_app, request
|
from flask.globals import session, _request_ctx_stack, current_app, request
|
||||||
from flask.wrappers import Response
|
from flask.wrappers import Response
|
||||||
|
|
@ -199,7 +201,8 @@ def get_flashed_messages(with_categories=False):
|
||||||
|
|
||||||
|
|
||||||
def send_file(filename_or_fp, mimetype=None, as_attachment=False,
|
def send_file(filename_or_fp, mimetype=None, as_attachment=False,
|
||||||
attachment_filename=None):
|
attachment_filename=None, add_etags=True,
|
||||||
|
cache_timeout=60 * 60 * 12, conditional=False):
|
||||||
"""Sends the contents of a file to the client. This will use the
|
"""Sends the contents of a file to the client. This will use the
|
||||||
most efficient method available and configured. By default it will
|
most efficient method available and configured. By default it will
|
||||||
try to use the WSGI server's file_wrapper support. Alternatively
|
try to use the WSGI server's file_wrapper support. Alternatively
|
||||||
|
|
@ -220,6 +223,10 @@ def send_file(filename_or_fp, mimetype=None, as_attachment=False,
|
||||||
|
|
||||||
.. versionadded:: 0.2
|
.. versionadded:: 0.2
|
||||||
|
|
||||||
|
.. versionadded:: 0.5
|
||||||
|
The `add_etags`, `cache_timeout` and `conditional` parameters were added.
|
||||||
|
The default behaviour is now to attach etags.
|
||||||
|
|
||||||
:param filename_or_fp: the filename of the file to send. This is
|
:param filename_or_fp: the filename of the file to send. This is
|
||||||
relative to the :attr:`~Flask.root_path` if a
|
relative to the :attr:`~Flask.root_path` if a
|
||||||
relative path is specified.
|
relative path is specified.
|
||||||
|
|
@ -232,6 +239,9 @@ def send_file(filename_or_fp, mimetype=None, as_attachment=False,
|
||||||
a ``Content-Disposition: attachment`` header.
|
a ``Content-Disposition: attachment`` header.
|
||||||
:param attachment_filename: the filename for the attachment if it
|
:param attachment_filename: the filename for the attachment if it
|
||||||
differs from the file's filename.
|
differs from the file's filename.
|
||||||
|
:param add_etags: set to `False` to disable attaching of etags.
|
||||||
|
:param conditional: set to `True` to enable conditional responses.
|
||||||
|
:param cache_timeout: the timeout in seconds for the headers.
|
||||||
"""
|
"""
|
||||||
if isinstance(filename_or_fp, basestring):
|
if isinstance(filename_or_fp, basestring):
|
||||||
filename = filename_or_fp
|
filename = filename_or_fp
|
||||||
|
|
@ -266,8 +276,27 @@ def send_file(filename_or_fp, mimetype=None, as_attachment=False,
|
||||||
file = open(filename, 'rb')
|
file = open(filename, 'rb')
|
||||||
data = wrap_file(request.environ, file)
|
data = wrap_file(request.environ, file)
|
||||||
|
|
||||||
return Response(data, mimetype=mimetype, headers=headers,
|
rv = Response(data, mimetype=mimetype, headers=headers,
|
||||||
direct_passthrough=True)
|
direct_passthrough=True)
|
||||||
|
|
||||||
|
rv.cache_control.public = True
|
||||||
|
if cache_timeout:
|
||||||
|
rv.cache_control.max_age = cache_timeout
|
||||||
|
rv.expires = int(time() + cache_timeout)
|
||||||
|
|
||||||
|
if add_etags and filename is not None:
|
||||||
|
rv.set_etag('flask-%s-%s-%s' % (
|
||||||
|
os.path.getmtime(filename),
|
||||||
|
os.path.getsize(filename),
|
||||||
|
adler32(filename) & 0xffffffff
|
||||||
|
))
|
||||||
|
if conditional:
|
||||||
|
rv = rv.make_conditional(request)
|
||||||
|
# make sure we don't send x-sendfile for servers that
|
||||||
|
# ignore the 304 status code for x-sendfile.
|
||||||
|
if rv.status_code == 304:
|
||||||
|
rv.headers.pop('x-sendfile', None)
|
||||||
|
return rv
|
||||||
|
|
||||||
|
|
||||||
def render_template(template_name, **context):
|
def render_template(template_name, **context):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue