|
@@ -0,0 +1,122 @@
|
|
|
+from os import path, mkdir, getcwd
|
|
|
+from time import time
|
|
|
+from uuid import uuid1
|
|
|
+
|
|
|
+from eventlet import tpool
|
|
|
+from flask import Flask, request, make_response, send_from_directory
|
|
|
+
|
|
|
+from pycs.ApplicationStatus import ApplicationStatus
|
|
|
+
|
|
|
+
|
|
|
+class FileProvider(Flask):
|
|
|
+ def __init__(self, app_status: ApplicationStatus, cors=False):
|
|
|
+ super().__init__(__name__)
|
|
|
+
|
|
|
+ # add download handler
|
|
|
+ @self.route('/media/<identifier>', methods=['GET'])
|
|
|
+ def media(identifier):
|
|
|
+ # get current project
|
|
|
+ opened_projects = list(filter(lambda x: x['status'] == 'open', app_status['projects']))
|
|
|
+ if len(opened_projects) == 0:
|
|
|
+ return make_response('no open project available', 500)
|
|
|
+
|
|
|
+ current_project = opened_projects[0]
|
|
|
+ file_directory = path.join(getcwd(), 'projects', current_project['id'], 'data')
|
|
|
+
|
|
|
+ # get object
|
|
|
+ data_objects = list(filter(lambda x: x['id'] == identifier, current_project['data']))
|
|
|
+ if len(data_objects) == 0:
|
|
|
+ return make_response('data object not avilable', 500)
|
|
|
+
|
|
|
+ target_object = data_objects[0]
|
|
|
+
|
|
|
+ # return data
|
|
|
+ file_name = target_object['id'] + target_object['extension']
|
|
|
+ return send_from_directory(file_directory, file_name)
|
|
|
+
|
|
|
+ # add upload handler
|
|
|
+ @self.route('/upload', methods=['POST'])
|
|
|
+ def upload():
|
|
|
+ file_uuid = str(uuid1())
|
|
|
+
|
|
|
+ # get current project path
|
|
|
+ opened_projects = list(filter(lambda x: x['status'] == 'open', app_status['projects']))
|
|
|
+ if len(opened_projects) == 0:
|
|
|
+ return make_response('no open project available', 500)
|
|
|
+
|
|
|
+ current_project = opened_projects[0]
|
|
|
+ upload_path = path.join('projects', current_project['id'], 'data')
|
|
|
+
|
|
|
+ # get file object
|
|
|
+ # TODO read stream and parse data
|
|
|
+ # TODO update progress correctly
|
|
|
+ files = request.files
|
|
|
+
|
|
|
+ if 'file' not in files.keys():
|
|
|
+ return make_response('no file uploaded', 500)
|
|
|
+
|
|
|
+ file = files['file']
|
|
|
+ file_name = file.filename
|
|
|
+
|
|
|
+ # add job to app status
|
|
|
+ job = app_status['jobs'].append({
|
|
|
+ 'id': file_uuid,
|
|
|
+ 'type': 'upload',
|
|
|
+ 'progress': 0,
|
|
|
+ 'filename': file_name,
|
|
|
+ 'created': int(time()),
|
|
|
+ 'finished': None
|
|
|
+ })
|
|
|
+
|
|
|
+ if not path.exists(upload_path):
|
|
|
+ mkdir(upload_path)
|
|
|
+
|
|
|
+ # open file handler
|
|
|
+ file_name, file_extension = path.splitext(file_name)
|
|
|
+ file_path = path.join(upload_path, f'{file_uuid}{file_extension}')
|
|
|
+
|
|
|
+ with open(file_path, 'wb') as file_handler:
|
|
|
+ # prepare some properties
|
|
|
+ file_size = int(request.form['size']) if 'size' in request.form.keys() else None
|
|
|
+ file_stream = file.stream
|
|
|
+
|
|
|
+ # define handler function
|
|
|
+ def file_write():
|
|
|
+ data = file_stream.read(262144) # 256 kiB
|
|
|
+ file_handler.write(data)
|
|
|
+ return len(data)
|
|
|
+
|
|
|
+ # transfer blocks to storage and update progress
|
|
|
+ progress = 0
|
|
|
+ while True:
|
|
|
+ read_bytes = tpool.execute(file_write)
|
|
|
+ progress += read_bytes
|
|
|
+
|
|
|
+ if file_size is not None:
|
|
|
+ job['progress'] = progress / file_size
|
|
|
+
|
|
|
+ if read_bytes == 0:
|
|
|
+ break
|
|
|
+
|
|
|
+ # set progress to 1 after upload is done
|
|
|
+ job['progress'] = 1
|
|
|
+ job['finished'] = int(time())
|
|
|
+
|
|
|
+ # add to project files
|
|
|
+ if 'data' not in current_project:
|
|
|
+ current_project['data'] = []
|
|
|
+
|
|
|
+ current_project['data'].append({
|
|
|
+ 'id': file_uuid,
|
|
|
+ 'name': file_name,
|
|
|
+ 'extension': file_extension,
|
|
|
+ 'size': progress,
|
|
|
+ 'created': job['created']
|
|
|
+ })
|
|
|
+
|
|
|
+ # create response and allow cors if needed
|
|
|
+ response = make_response()
|
|
|
+ if cors:
|
|
|
+ response.headers['Access-Control-Allow-Origin'] = '*'
|
|
|
+
|
|
|
+ return response
|