diff --git a/owl/__init__.py b/owl/__init__.py index 86fde2f1181c95a79d86608b7182c2be4767352a..146b117720ce2a0cbac8755cf83e8800ce243319 100644 --- a/owl/__init__.py +++ b/owl/__init__.py @@ -7,6 +7,7 @@ import logging import os from sqlalchemy import select from sqlalchemy.orm import joinedload +import tempfile import werkzeug.exceptions import owl.assets as assets @@ -14,6 +15,35 @@ import owl.config as config import owl.db as db +# We wrap Flask to make it store uploaded files in a directory of our choice. +# This enables us to hard-link the uploaded files to their final place. +# To achieve that, we subclass Request to make it use a subclassed FormDataParser, +# which calls a custom stream factory. + +def owl_stream_factory(total_content_length, filename, content_type, content_length=None): + return tempfile.NamedTemporaryFile(dir=os.path.join(app.instance_path, 'tmp'), prefix='upload-') + + +class FormDataParser(werkzeug.formparser.FormDataParser): + + def __init__(self, + stream_factory=None, + charset='utf-8', + errors='replace', + max_form_memory_size=None, + max_content_length=None, + cls=None, + silent=True): + super().__init__(owl_stream_factory, charset, errors, max_form_memory_size, max_content_length, cls, silent) + + +class Request(flask.wrappers.Request): + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.form_data_parser_class = FormDataParser + + class OwlFlask(Flask): """ @@ -106,6 +136,7 @@ static_dir = os.path.abspath('static') # Application object app = OwlFlask(__name__, static_folder=static_dir, instance_path=data_dir) app.config.from_object(config) +app.request_class = Request db.flask_db = SQLAlchemy(app, metadata=db.metadata)