(self, request, project_pk=None)
| 710 | parser_classes = (parsers.MultiPartParser, parsers.JSONParser, parsers.FormParser,) |
| 711 | |
| 712 | def post(self, request, project_pk=None): |
| 713 | project = get_and_check_project(request, project_pk, ('change_project',)) |
| 714 | |
| 715 | files = flatten_files(request.FILES) |
| 716 | import_url = request.data.get('url', None) |
| 717 | task_name = request.data.get('name', _('Imported Task')) |
| 718 | public = bool(serializers.BooleanField(default=False, allow_null=True).to_internal_value(request.data.get('public', ''))) |
| 719 | |
| 720 | if not import_url and len(files) != 1: |
| 721 | raise exceptions.ValidationError(detail=_("Cannot create task, you need to upload 1 file")) |
| 722 | |
| 723 | if import_url: |
| 724 | if len(files) > 0: |
| 725 | raise exceptions.ValidationError(detail=_("Cannot create task, either specify a URL or upload 1 file.")) |
| 726 | if re.match(r"^https?:\/\/.+$", import_url.lower()) is None: |
| 727 | raise exceptions.ValidationError(detail=_("Invalid URL. Did you mean %(hint)s ?") % { 'hint': f'http://{import_url}'}) |
| 728 | |
| 729 | chunk_index = request.data.get('dzchunkindex') |
| 730 | uuid = request.data.get('dzuuid') |
| 731 | total_chunk_count = request.data.get('dztotalchunkcount', None) |
| 732 | |
| 733 | # Chunked upload? |
| 734 | tmp_upload_file = None |
| 735 | if len(files) > 0 and chunk_index is not None and uuid is not None and total_chunk_count is not None: |
| 736 | byte_offset = request.data.get('dzchunkbyteoffset', 0) |
| 737 | |
| 738 | try: |
| 739 | chunk_index = int(chunk_index) |
| 740 | byte_offset = int(byte_offset) |
| 741 | total_chunk_count = int(total_chunk_count) |
| 742 | except ValueError: |
| 743 | raise exceptions.ValidationError(detail="Some parameters are not integers") |
| 744 | uuid = re.sub('[^0-9a-zA-Z-]+', "", uuid) |
| 745 | |
| 746 | tmp_upload_file = os.path.join(settings.FILE_UPLOAD_TEMP_DIR, f"{uuid}.upload") |
| 747 | if os.path.isfile(tmp_upload_file) and chunk_index == 0: |
| 748 | os.unlink(tmp_upload_file) |
| 749 | |
| 750 | with open(tmp_upload_file, 'ab') as fd: |
| 751 | fd.truncate(byte_offset) |
| 752 | fd.seek(byte_offset) |
| 753 | if isinstance(files[0], InMemoryUploadedFile): |
| 754 | for chunk in files[0].chunks(): |
| 755 | fd.write(chunk) |
| 756 | else: |
| 757 | with open(files[0].temporary_file_path(), 'rb') as f: |
| 758 | shutil.copyfileobj(f, fd) |
| 759 | |
| 760 | if chunk_index + 1 < total_chunk_count: |
| 761 | return Response({'uploaded': True}, status=status.HTTP_200_OK) |
| 762 | |
| 763 | # Ready to import |
| 764 | with transaction.atomic(): |
| 765 | task = models.Task.objects.create(project=project, |
| 766 | auto_processing_node=False, |
| 767 | name=task_name, |
| 768 | import_url=import_url if import_url else "file://all.zip", |
| 769 | status=status_codes.RUNNING, |
nothing calls this directly
no test coverage detected