123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- 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
|