UploadFile.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. import os
  2. import uuid
  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.Project import Project
  8. from pycs.frontend.notifications.NotificationManager import NotificationManager
  9. from pycs.util.FileOperations 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, nm: NotificationManager):
  17. # pylint: disable=invalid-name
  18. self.nm = nm
  19. self.data_folder = None
  20. self.uuid = None
  21. self.name = None
  22. self.extension = None
  23. self.size = None
  24. def dispatch_request(self, project_id: int):
  25. # find project
  26. project = Project.get_or_404(project_id)
  27. # abort if external storage is used
  28. if project.external_data:
  29. return abort(400, "Project uses external data, but a file was uploaded")
  30. # get upload path and id
  31. self.data_folder = project.data_folder
  32. self.uuid = str(uuid.uuid1())
  33. # parse upload data
  34. _, _, files = tpool.execute(formparser.parse_form_data,
  35. request.environ,
  36. stream_factory=self.custom_stream_factory)
  37. # abort if there is no file entry in uploaded data
  38. if 'file' not in files.keys():
  39. return abort(400, "No file entry was found in uploaded data")
  40. # detect file type
  41. try:
  42. ftype, frames, fps = tpool.execute(file_info,
  43. self.data_folder,
  44. self.uuid,
  45. self.extension)
  46. except ValueError as exception:
  47. return abort(400, str(exception))
  48. file, _ = project.add_file(
  49. uuid=self.uuid,
  50. file_type=ftype,
  51. name=self.name,
  52. extension=self.extension,
  53. size=self.size,
  54. filename=self.uuid,
  55. frames=frames,
  56. fps=fps)
  57. # send update
  58. self.nm.create_file(file)
  59. # return default success response
  60. return make_response()
  61. def custom_stream_factory(self, total_content_length, filename, content_type,
  62. content_length=None):
  63. """
  64. save some useful information and open a file handler to save the uploaded file to
  65. :param total_content_length:
  66. :param filename:
  67. :param content_type:
  68. :param content_length:
  69. :return:
  70. """
  71. # pylint: disable=unused-argument
  72. # set relevant properties
  73. self.name, self.extension = os.path.splitext(filename)
  74. if content_length is not None and content_length > 0:
  75. self.size = content_length
  76. else:
  77. self.size = total_content_length
  78. # open file handler
  79. file_path = os.path.join(self.data_folder, f'{self.uuid}{self.extension}')
  80. #pylint: disable=consider-using-with
  81. return open(file_path, 'wb')