def upload_instructor_archive(self, request, suffix): """ Обработчик загрузки архива инструктора. Вызывается, когда в студии инструктор нажимает кнопку "Загрузить" напротив поля "Архив инструктора". Проводит валидацию архива и временно сохраняет его. Позднее, он может быт восстановлен обработчиком "save_settings". Защиты от параллельной загрузки несколькими инструкторами (или в нескольких окнах браузера) не предусмотрено. :param request: :param suffix: :return: """ def get_archive_signature(archive): """ Формирует подпись архива (файла) на основании sha1 и текущего времени :param archive: file-object :return: tuple(sha1, signature) """ import hashlib import datetime sha1 = get_sha1(archive) md5 = hashlib.md5() md5.update(sha1) md5.update(datetime.datetime.isoformat(datetime.datetime.now())) return sha1, md5.hexdigest() upload = request.params['instructor_archive'] self.validate_instructor_archive(upload.file) uploaded_file = File(upload.file) archive_sha1, archive_signature = get_archive_signature(uploaded_file) archive_name = "instructor.{signature}.~draft".format( name=upload.file.name, signature=archive_signature) fs_path = file_storage_path(self.location, archive_name) # Сохраняем временную информацию до того как нажата кнопка "Save" self.instructor_archive_meta['draft'] = { 'filename': upload.file.name, 'sha1': get_sha1(uploaded_file), 'upload_at': None, 'upload_by': None, 'fs_path': fs_path, } if default_storage.exists(fs_path): default_storage.delete(fs_path) default_storage.save(fs_path, uploaded_file) return Response(json_body={})
def get_archive_signature(archive): """ Формирует подпись архива (файла) на основании sha1 и текущего времени :param archive: file-object :return: tuple(sha1, signature) """ import hashlib import datetime sha1 = get_sha1(archive) md5 = hashlib.md5() md5.update(sha1) md5.update(datetime.datetime.isoformat(datetime.datetime.now())) return sha1, md5.hexdigest()
def upload_submission(self, request, suffix): def _return_response(response_update=None): if response_update is None: response_update = {} response = self.get_student_context() response.update(response_update) return self.get_response_user_state(response) if self.queue_details: return _return_response({ 'message': { 'text': 'Проверка другого решения уже запущена.', 'type': 'error', } }) try: self.message = None # Извлечение данных о загруженном файле upload = request.params['submission'] uploaded_file = File(upload.file) uploaded_filename = upload.file.name uploaded_sha1 = get_sha1(upload.file) uploaded_mimetype = mimetypes.guess_type(upload.file.name)[0] # Реальные названия файлов в ФС fs_path = file_storage_path(self.location, uploaded_sha1) instructor_fs_path = self.get_instructor_path() # Сохраняем данные о решении student_id = self.student_submission_dict() student_answer = { "sha1": uploaded_sha1, "filename": uploaded_filename, "mimetype": uploaded_mimetype, "real_path": fs_path, "instructor_real_path": instructor_fs_path, } submission = submissions_api.create_submission( student_id, student_answer) # Сохраняем файл с решением if default_storage.exists(fs_path): default_storage.delete(fs_path) default_storage.save(fs_path, uploaded_file) payload = { 'method': 'check', 'student_info': self.queue_student_info, 'grader_payload': json.dumps({ 'pregenerated': self.pregenerated if self.need_generate else None, 'time_limit_execute': self.time_limit_execute, 'time_limit_check': self.time_limit_check, }), 'student_response': self.get_queue_student_response(submission), } self.send_to_queue(header=self.get_submission_header( access_key_prefix=submission.get('uuid'), ), body=json.dumps(payload)) except Exception as e: return _return_response({ 'message': { 'text': 'Ошибка при попытке поставить проверку решения в очередь: ' + e.message, 'type': 'error', } }) return _return_response()