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)