6
0

UploadFile.py 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  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.Project import Project
  8. from pycs.database.File import File
  9. from pycs.frontend.notifications.NotificationManager import NotificationManager
  10. from pycs.util.FileParser import file_info
  11. class UploadFile(View):
  12. """
  13. save file uploads
  14. """
  15. # pylint: disable=arguments-differ
  16. methods = ['POST']
  17. def __init__(self):
  18. self.data_folder = None
  19. self.file_id = None
  20. self.file_name = None
  21. self.file_extension = None
  22. self.file_size = None
  23. def dispatch_request(self, identifier):
  24. # find project
  25. project = Project.query.get(identifier)
  26. if project is None:
  27. return abort(404, "Project not found")
  28. # abort if external storage is used
  29. if project.external_data:
  30. return abort(400, "Project uses external data, but a file was uploaded")
  31. # get upload path and id
  32. self.data_folder = project.data_folder
  33. self.file_id = str(uuid1())
  34. # parse upload data
  35. _, _, files = tpool.execute(formparser.parse_form_data,
  36. request.environ, 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, self.file_id, self.file_extension)
  44. except ValueError as exception:
  45. return abort(400, str(exception))
  46. file, _ = project.add_file(self.file_id, ftype, self.file_name, self.file_extension,
  47. self.file_size, self.file_id, frames, fps)
  48. # send update
  49. NotificationManager.created("file", file.id, File)
  50. # return default success response
  51. return make_response()
  52. def custom_stream_factory(self, total_content_length, content_type, filename=None,
  53. content_length=None):
  54. """
  55. save some useful information and open a file handler to save the uploaded file to
  56. :param total_content_length:
  57. :param filename:
  58. :param content_type:
  59. :param content_length:
  60. :return:
  61. """
  62. # pylint: disable=unused-argument
  63. # set relevant properties
  64. self.file_name, self.file_extension = path.splitext(filename)
  65. if content_length is not None and content_length > 0:
  66. self.file_size = content_length
  67. else:
  68. self.file_size = total_content_length
  69. # open file handler
  70. file_path = path.join(self.data_folder, f'{self.file_id}{self.file_extension}')
  71. return open(file_path, 'wb')