import os import uuid from pathlib import Path from django.conf import settings from django.views.static import serve as static_serve from rest_framework.decorators import api_view, permission_classes, parser_classes from rest_framework.permissions import IsAuthenticated from rest_framework.parsers import MultiPartParser from rest_framework.response import Response from rest_framework import status H5_DIST_ROOT = Path(settings.BASE_DIR).parent / 'frontend-h5' / 'dist' def serve_h5(request, path=''): """ H5 SPA 静态资源 + history 路由回退。 - /m/ 或 /m/(无扩展名/不存在的路径)→ 返回 dist/index.html - /m/assets/xxx.js, /m/img/xxx.jpg 等真实存在的文件 → 直出 """ if path: candidate = H5_DIST_ROOT / path if candidate.is_file(): return static_serve(request, path, document_root=str(H5_DIST_ROOT)) return static_serve(request, 'index.html', document_root=str(H5_DIST_ROOT)) ALLOWED_IMAGE_TYPES = { 'image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/bmp', } MAX_FILE_SIZE = 10 * 1024 * 1024 # 10MB @api_view(['POST']) @permission_classes([IsAuthenticated]) @parser_classes([MultiPartParser]) def upload_image(request): file = request.FILES.get('file') if not file: return Response({'detail': '未提供文件'}, status=status.HTTP_400_BAD_REQUEST) if file.content_type not in ALLOWED_IMAGE_TYPES: return Response( {'detail': '仅支持 JPG/PNG/GIF/WEBP/BMP 格式的图片'}, status=status.HTTP_400_BAD_REQUEST, ) if file.size > MAX_FILE_SIZE: return Response( {'detail': '文件大小不能超过 10MB'}, status=status.HTTP_400_BAD_REQUEST, ) ext = os.path.splitext(file.name)[1].lower() filename = f"{uuid.uuid4().hex}{ext}" relative_path = f"uploads/{filename}" full_path = os.path.join(settings.MEDIA_ROOT, relative_path) os.makedirs(os.path.dirname(full_path), exist_ok=True) with open(full_path, 'wb+') as dest: for chunk in file.chunks(): dest.write(chunk) url = request.build_absolute_uri(f"/{settings.MEDIA_URL}{relative_path}") return Response({'url': url, 'path': relative_path})