model_train_dm/backend/apps/datasets/views/temp_file.py

172 lines
6.1 KiB
Python
Raw Normal View History

2026-07-27 17:51:49 +08:00
import mimetypes
import os
import uuid
from datetime import datetime
from django.conf import settings
from django.shortcuts import get_object_or_404
from django.http import StreamingHttpResponse
from rest_framework import status
from rest_framework.decorators import api_view, parser_classes, permission_classes
from rest_framework.pagination import PageNumberPagination
from rest_framework.parsers import MultiPartParser
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from apps.common.minio_client import minio_storage
from apps.common.serializers import AiTempFileSerializer
from apps.core.models import AiTempFile
TEMPFILE_BUCKET = "tempfile"
IMAGE_TYPES = {".jpg", ".jpeg", ".png", ".bmp", ".gif", ".webp", ".tif", ".tiff"}
VIDEO_TYPES = {".mp4", ".avi", ".mov", ".mkv", ".wmv", ".flv", ".mpeg", ".mpg", ".webm"}
AUDIO_TYPES = {".mp3", ".wav", ".aac", ".m4a", ".flac", ".ogg"}
TEXT_TYPES = {".txt", ".csv", ".json", ".xml"}
def _detect_original_type(filename: str) -> str:
ext = os.path.splitext(filename or "")[1].lower()
if ext in IMAGE_TYPES:
return "01"
if ext in VIDEO_TYPES:
return "02"
if ext in AUDIO_TYPES:
return "03"
if ext == ".zip":
return "04"
if ext in TEXT_TYPES:
return "05"
return "99"
def _stream_object(response, chunk_size: int = 1024 * 1024):
try:
while True:
chunk = response.read(chunk_size)
if not chunk:
break
yield chunk
finally:
response.close()
response.release_conn()
@api_view(["POST"])
@parser_classes([MultiPartParser])
@permission_classes([IsAuthenticated])
def upload_temp_file(request):
uploaded_file = request.FILES.get("file")
if not uploaded_file:
return Response({"error": "缺少 file 字段"}, status=status.HTTP_400_BAD_REQUEST)
file_id = str(uuid.uuid4())
bucket_name = request.data.get("bucket_name") or TEMPFILE_BUCKET
prefix = request.data.get("prefix") or datetime.now().strftime("%Y-%m-%d")
object_name = request.data.get("object_name") or minio_storage.generate_object_name(uploaded_file.name, prefix)
content_type = uploaded_file.content_type or mimetypes.guess_type(uploaded_file.name)[0] or "application/octet-stream"
original_type = request.data.get("original_type") or _detect_original_type(uploaded_file.name)
minio_storage.upload_stream(
bucket_name=bucket_name,
object_name=object_name,
data=uploaded_file.file,
length=uploaded_file.size,
content_type=content_type,
)
obj = AiTempFile.objects.create(
id=file_id,
original_path=request.data.get("original_path") or "",
original_name=uploaded_file.name,
original_type=original_type,
bucket_name=bucket_name,
object_name=object_name,
object_size=uploaded_file.size,
content_type=content_type,
status=request.data.get("status") or "01",
)
serializer = AiTempFileSerializer(obj)
return Response({"message": "临时文件上传成功", "data": serializer.data})
@api_view(["GET"])
@permission_classes([IsAuthenticated])
def search_temp_files(request):
filter_kwargs = {}
original_name = request.GET.get("original_name")
original_type = request.GET.get("original_type")
status_code = request.GET.get("status")
page_size = request.GET.get("page_size") or 10
if original_name:
filter_kwargs["original_name__contains"] = original_name
if original_type:
filter_kwargs["original_type"] = original_type
if status_code:
filter_kwargs["status"] = status_code
queryset = AiTempFile.objects.filter(**filter_kwargs).order_by("-create_time")
paginator = PageNumberPagination()
paginator.page_size = page_size
page = paginator.paginate_queryset(queryset, request)
serializer = AiTempFileSerializer(page, many=True)
return paginator.get_paginated_response(serializer.data)
@api_view(["GET"])
@permission_classes([IsAuthenticated])
def read_temp_file(request):
temp_id = request.GET.get("id")
obj = get_object_or_404(AiTempFile, id=temp_id)
serializer = AiTempFileSerializer(obj)
return Response(serializer.data)
@api_view(["PUT"])
@permission_classes([IsAuthenticated])
def update_temp_file(request):
data = request.data
obj = get_object_or_404(AiTempFile, id=data.get("id"))
serializer = AiTempFileSerializer(instance=obj, data=data, partial=True)
if serializer.is_valid():
serializer.save()
return Response({"message": "临时文件更新成功"})
return Response({"error": "无效的数据", "details": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
@api_view(["DELETE"])
@permission_classes([IsAuthenticated])
def delete_temp_file(request):
temp_id = request.GET.get("id")
obj = get_object_or_404(AiTempFile, id=temp_id)
if obj.bucket_name and obj.object_name:
minio_storage.delete_object(obj.bucket_name, obj.object_name)
obj.delete()
return Response({"message": "临时文件删除成功"})
@api_view(["GET"])
@permission_classes([IsAuthenticated])
def download_temp_file(request):
temp_id = request.GET.get("id")
obj = get_object_or_404(AiTempFile, id=temp_id)
response = minio_storage.get_object(obj.bucket_name, obj.object_name)
content_type = obj.content_type or "application/octet-stream"
filename = obj.original_name or os.path.basename(obj.object_name or "")
stream = StreamingHttpResponse(_stream_object(response), content_type=content_type)
stream["Content-Disposition"] = f'attachment; filename="{filename}"'
return stream
@api_view(["GET"])
@permission_classes([IsAuthenticated])
def preview_temp_file(request):
temp_id = request.GET.get("id")
obj = get_object_or_404(AiTempFile, id=temp_id)
response = minio_storage.get_object(obj.bucket_name, obj.object_name)
content_type = obj.content_type or "application/octet-stream"
stream = StreamingHttpResponse(_stream_object(response), content_type=content_type)
stream["Content-Disposition"] = "inline"
return stream