UploadFile.py 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. from os import path
  2. from uuid import uuid1
  3. from eventlet import tpool
  4. from flask import make_response, request, abort
  5. from flask.views import View
  6. from werkzeug import formparser
  7. from pycs.database.Database import Database
  8. from pycs.frontend.notifications.NotificationManager import NotificationManager
  9. from pycs.util.FileParser import file_info
  10. class UploadFile(View):
  11. """
  12. save file uploads
  13. """
  14. # pylint: disable=arguments-differ
  15. methods = ['POST']
  16. def __init__(self, db: Database, nm: NotificationManager):
  17. # pylint: disable=invalid-name
  18. self.db = db
  19. self.nm = nm
  20. self.data_folder = None
  21. self.file_id = None
  22. self.file_name = None
  23. self.file_extension = None
  24. self.file_size = None
  25. def dispatch_request(self, identifier):
  26. # find project
  27. project = self.db.project(identifier)
  28. if project is None:
  29. return abort(404)
  30. # abort if external storage is used
  31. if project.external_data:
  32. return abort(400)
  33. # get upload path and id
  34. self.data_folder = project.data_folder
  35. self.file_id = str(uuid1())
  36. # parse upload data
  37. _, _, files = tpool.execute(formparser.parse_form_data,
  38. request.environ, stream_factory=self.custom_stream_factory)
  39. # abort if there is no file entry in uploaded data
  40. if 'file' not in files.keys():
  41. return abort(400)
  42. # detect file type
  43. try:
  44. ftype, frames, fps = file_info(self.data_folder, self.file_id, self.file_extension)
  45. except ValueError:
  46. return abort(400)
  47. # add to project files
  48. with self.db:
  49. file, _ = project.add_file(self.file_id, ftype, self.file_name, self.file_extension,
  50. self.file_size, self.file_id, frames, fps)
  51. # send update
  52. self.nm.create_file(file)
  53. # return default success response
  54. return make_response()
  55. def custom_stream_factory(self, total_content_length, filename, content_type,
  56. content_length=None):
  57. """
  58. save some useful information and open a file handler to save the uploaded file to
  59. :param total_content_length:
  60. :param filename:
  61. :param content_type:
  62. :param content_length:
  63. :return:
  64. """
  65. # pylint: disable=unused-argument
  66. # set relevant properties
  67. self.file_name, self.file_extension = path.splitext(filename)
  68. if content_length is not None and content_length > 0:
  69. self.file_size = content_length
  70. else:
  71. self.file_size = total_content_length
  72. # open file handler
  73. file_path = path.join(self.data_folder, f'{self.file_id}{self.file_extension}')
  74. return open(file_path, 'wb')