Add an option to the static() helper to switch on streaming for large files.

By default uses a 1M threshold.
ie. if the static file to serve is >= 1M it will stream the file.
This threshold value is configurable by passing an int instead of a bool to `stream_large_files` parameter of `static()`.
This commit is contained in:
ashleysommer 2017-05-18 18:30:54 +10:00 committed by Ashley Sommer
parent 0858d3c544
commit 72db1188c7
2 changed files with 21 additions and 4 deletions

View File

@ -299,12 +299,14 @@ class Sanic:
# Static Files # Static Files
def static(self, uri, file_or_directory, pattern=r'/?.+', def static(self, uri, file_or_directory, pattern=r'/?.+',
use_modified_since=True, use_content_range=False): use_modified_since=True, use_content_range=False,
stream_large_files=False):
"""Register a root to serve files from. The input can either be a """Register a root to serve files from. The input can either be a
file or a directory. See file or a directory. See
""" """
static_register(self, uri, file_or_directory, pattern, static_register(self, uri, file_or_directory, pattern,
use_modified_since, use_content_range) use_modified_since, use_content_range,
stream_large_files)
def blueprint(self, blueprint, **options): def blueprint(self, blueprint, **options):
"""Register a blueprint on the application. """Register a blueprint on the application.

View File

@ -13,11 +13,12 @@ from sanic.exceptions import (
InvalidUsage, InvalidUsage,
) )
from sanic.handlers import ContentRangeHandler from sanic.handlers import ContentRangeHandler
from sanic.response import file, HTTPResponse from sanic.response import file, file_stream, HTTPResponse
def register(app, uri, file_or_directory, pattern, def register(app, uri, file_or_directory, pattern,
use_modified_since, use_content_range): use_modified_since, use_content_range,
stream_large_files):
# TODO: Though sanic is not a file server, I feel like we should at least # TODO: Though sanic is not a file server, I feel like we should at least
# make a good effort here. Modified-since is nice, but we could # make a good effort here. Modified-since is nice, but we could
# also look into etags, expires, and caching # also look into etags, expires, and caching
@ -34,6 +35,10 @@ def register(app, uri, file_or_directory, pattern,
server's server's
:param use_content_range: If true, process header for range requests :param use_content_range: If true, process header for range requests
and sends the file part that is requested and sends the file part that is requested
:param stream_large_files: If true, use the file_stream() handler rather
than the file() handler to send the file
If this is an integer, this represents the
threshold size to switch to file_stream()
""" """
# If we're not trying to match a file directly, # If we're not trying to match a file directly,
# serve from the folder # serve from the folder
@ -93,6 +98,16 @@ def register(app, uri, file_or_directory, pattern,
headers=headers, headers=headers,
content_type=guess_type(file_path)[0] or 'text/plain') content_type=guess_type(file_path)[0] or 'text/plain')
else: else:
if stream_large_files:
if isinstance(stream_large_files, int):
threshold = stream_large_files
else:
threshold = 1024*1000
if not stats:
stats = await stat(file_path)
if stats.st_size >= threshold:
return await file_stream(file_path, headers=headers, _range=_range)
return await file(file_path, headers=headers, _range=_range) return await file(file_path, headers=headers, _range=_range)
except ContentRangeError: except ContentRangeError:
raise raise