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:
parent
0858d3c544
commit
72db1188c7
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue
Block a user