|
@@ -2,10 +2,12 @@ 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 flask import Flask, make_response, send_from_directory, request
|
|
|
+from werkzeug import formparser
|
|
|
|
|
|
from pycs.ApplicationStatus import ApplicationStatus
|
|
|
+from pycs.util.GenericWrapper import GenericWrapper
|
|
|
+from pycs.util.ProgressFileWriter import ProgressFileWriter
|
|
|
|
|
|
|
|
|
class FileProvider(Flask):
|
|
@@ -47,58 +49,51 @@ class FileProvider(Flask):
|
|
|
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
|
|
|
+ job = GenericWrapper()
|
|
|
+ file_name = GenericWrapper()
|
|
|
+ file_extension = GenericWrapper()
|
|
|
+ file_size = GenericWrapper(0)
|
|
|
|
|
|
- if 'file' not in files.keys():
|
|
|
- return make_response('no file uploaded', 500)
|
|
|
+ # save upload to file
|
|
|
+ def custom_stream_factory(total_content_length, filename, content_type, content_length=None):
|
|
|
+ file_name.value, file_extension.value = path.splitext(filename)
|
|
|
+ file_path = path.join(upload_path, f'{file_uuid}{file_extension.value}')
|
|
|
|
|
|
- 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
|
|
|
- })
|
|
|
+ # add job to app status
|
|
|
+ job.value = app_status['jobs'].append({
|
|
|
+ 'id': file_uuid,
|
|
|
+ 'type': 'upload',
|
|
|
+ 'progress': 0,
|
|
|
+ 'filename': filename,
|
|
|
+ 'created': int(time()),
|
|
|
+ 'finished': None
|
|
|
+ })
|
|
|
|
|
|
- if not path.exists(upload_path):
|
|
|
- mkdir(upload_path)
|
|
|
+ # create upload path if not exists
|
|
|
+ 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}')
|
|
|
+ # define progress callback
|
|
|
+ length = content_length if content_length is not None and content_length != 0 else total_content_length
|
|
|
|
|
|
- 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
|
|
|
+ def callback(progress):
|
|
|
+ file_size.value += progress
|
|
|
+ relative = progress / length
|
|
|
|
|
|
- # define handler function
|
|
|
- def file_write():
|
|
|
- data = file_stream.read(262144) # 256 kiB
|
|
|
- file_handler.write(data)
|
|
|
- return len(data)
|
|
|
+ if relative - job.value['progress'] > 0.02:
|
|
|
+ job.value['progress'] = relative
|
|
|
|
|
|
- # transfer blocks to storage and update progress
|
|
|
- progress = 0
|
|
|
- while True:
|
|
|
- read_bytes = tpool.execute(file_write)
|
|
|
- progress += read_bytes
|
|
|
+ # open file handler
|
|
|
+ return ProgressFileWriter(file_path, 'wb', callback)
|
|
|
|
|
|
- if file_size is not None:
|
|
|
- job['progress'] = progress / file_size
|
|
|
+ stream, form, files = formparser.parse_form_data(request.environ, stream_factory=custom_stream_factory)
|
|
|
|
|
|
- if read_bytes == 0:
|
|
|
- break
|
|
|
+ if 'file' not in files.keys():
|
|
|
+ return make_response('no file uploaded', 500)
|
|
|
|
|
|
# set progress to 1 after upload is done
|
|
|
+ job = job.value
|
|
|
+
|
|
|
job['progress'] = 1
|
|
|
job['finished'] = int(time())
|
|
|
|
|
@@ -108,9 +103,9 @@ class FileProvider(Flask):
|
|
|
|
|
|
current_project['data'].append({
|
|
|
'id': file_uuid,
|
|
|
- 'name': file_name,
|
|
|
- 'extension': file_extension,
|
|
|
- 'size': progress,
|
|
|
+ 'name': file_name.value,
|
|
|
+ 'extension': file_extension.value,
|
|
|
+ 'size': file_size.value,
|
|
|
'created': job['created']
|
|
|
})
|
|
|
|