@@ -19,7 +19,9 @@ from rest_framework.viewsets import ModelViewSet
|
||||
|
||||
from apps.common.api import TeamScopedViewSetMixin, get_current_team
|
||||
|
||||
from . import assets_client
|
||||
from .models import Asset, AssetFile, Model
|
||||
from .review import wait_upload_review
|
||||
from .serializers import AssetSerializer, AssetUploadSerializer, ModelLibrarySerializer
|
||||
from .storage import TosStorage
|
||||
|
||||
@@ -778,7 +780,6 @@ class ModelLibraryViewSet(ModelViewSet):
|
||||
class AssetUploadView(APIView):
|
||||
parser_classes = [MultiPartParser, FormParser]
|
||||
|
||||
@transaction.atomic
|
||||
def post(self, request):
|
||||
serializer = AssetUploadSerializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
@@ -793,22 +794,52 @@ class AssetUploadView(APIView):
|
||||
object_key=object_key,
|
||||
content_type=upload.content_type or "application/octet-stream",
|
||||
)
|
||||
asset = Asset.objects.create(
|
||||
id=asset_id,
|
||||
team=team,
|
||||
created_by=request.user,
|
||||
name=serializer.validated_data.get("name") or upload.name,
|
||||
asset_type=serializer.validated_data["asset_type"],
|
||||
source=Asset.Source.UPLOAD,
|
||||
category=serializer.validated_data["category"],
|
||||
description=serializer.validated_data.get("description", ""),
|
||||
# 先持久化,审核服务才能从 TOS 拉取文件;网络审核绝不能放在数据库事务里,
|
||||
# 否则几十秒的轮询会长期锁住请求事务。
|
||||
with transaction.atomic():
|
||||
asset = Asset.objects.create(
|
||||
id=asset_id,
|
||||
team=team,
|
||||
created_by=request.user,
|
||||
name=serializer.validated_data.get("name") or upload.name,
|
||||
asset_type=serializer.validated_data["asset_type"],
|
||||
source=Asset.Source.UPLOAD,
|
||||
category=serializer.validated_data["category"],
|
||||
description=serializer.validated_data.get("description", ""),
|
||||
)
|
||||
AssetFile.objects.create(
|
||||
asset=asset,
|
||||
object_key=stored.object_key,
|
||||
bucket=stored.bucket,
|
||||
content_type=stored.content_type,
|
||||
size_bytes=stored.size_bytes,
|
||||
is_primary=True,
|
||||
)
|
||||
|
||||
# 所有本地上传(图片/视频/音频)一律 force 送审。未通过、审核中或审核
|
||||
# 服务不可用时都不返回 AssetSerializer,避免提前泄露可供生成使用的链接。
|
||||
if not assets_client.is_enabled():
|
||||
return Response(
|
||||
{"detail": "素材审核服务暂不可用,请稍后重试", "review_status": "unavailable", "asset_id": str(asset.id)},
|
||||
status=status.HTTP_503_SERVICE_UNAVAILABLE,
|
||||
)
|
||||
review_status = wait_upload_review(asset)
|
||||
asset.refresh_from_db()
|
||||
if review_status == "active":
|
||||
return Response(AssetSerializer(asset).data, status=status.HTTP_201_CREATED)
|
||||
if review_status == "failed":
|
||||
detail = (asset.review_error or "素材未通过审核,请更换后重试").strip()
|
||||
return Response(
|
||||
{"detail": detail, "review_status": "failed", "asset_id": str(asset.id)},
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
if review_status == "processing":
|
||||
return Response(
|
||||
{"detail": "素材仍在审核中,请稍后重试", "review_status": "processing", "asset_id": str(asset.id)},
|
||||
status=status.HTTP_408_REQUEST_TIMEOUT,
|
||||
)
|
||||
detail = (asset.review_error or "素材审核服务暂不可用,请稍后重试").strip()
|
||||
return Response(
|
||||
{"detail": detail, "review_status": "unavailable", "asset_id": str(asset.id)},
|
||||
status=status.HTTP_503_SERVICE_UNAVAILABLE,
|
||||
)
|
||||
AssetFile.objects.create(
|
||||
asset=asset,
|
||||
object_key=stored.object_key,
|
||||
bucket=stored.bucket,
|
||||
content_type=stored.content_type,
|
||||
size_bytes=stored.size_bytes,
|
||||
is_primary=True,
|
||||
)
|
||||
return Response(AssetSerializer(asset).data, status=status.HTTP_201_CREATED)
|
||||
|
||||
Reference in New Issue
Block a user