from rest_framework.decorators import api_view, parser_classes, authentication_classes, permission_classes from rest_framework.response import Response from rest_framework import status from rest_framework.parsers import MultiPartParser, FormParser from rest_framework.permissions import IsAuthenticated from django.views.decorators.csrf import csrf_exempt from .oss import OSSUploader from drf_yasg.utils import swagger_auto_schema from drf_yasg import openapi import logging from userapp.authentication import RedisTokenAuthentication logger = logging.getLogger(__name__) @swagger_auto_schema( method='post', operation_description="通用文件上传接口,上传到OSS", manual_parameters=[ openapi.Parameter( 'file', openapi.IN_FORM, description="需要上传的文件", type=openapi.TYPE_FILE, required=True ), openapi.Parameter( 'is_permanent', openapi.IN_FORM, description="是否永久保存文件,默认为临时文件", type=openapi.TYPE_BOOLEAN, default=False ), openapi.Parameter( 'filename', openapi.IN_FORM, description="自定义文件名(可选),如果不提供则自动生成", type=openapi.TYPE_STRING, required=False ), ], responses={ 200: openapi.Response( description="上传成功", schema=openapi.Schema( type=openapi.TYPE_OBJECT, properties={ 'url': openapi.Schema(type=openapi.TYPE_STRING, description="文件访问URL"), 'key': openapi.Schema(type=openapi.TYPE_STRING, description="OSS对象键名"), 'is_permanent': openapi.Schema(type=openapi.TYPE_BOOLEAN, description="是否永久文件") } ) ), 400: openapi.Response(description="请求错误或上传失败"), 401: openapi.Response(description="认证失败") }, tags=['文件上传'], security=[{'Bearer': []}] ) @csrf_exempt @api_view(['POST']) @parser_classes([MultiPartParser, FormParser]) @authentication_classes([RedisTokenAuthentication]) @permission_classes([IsAuthenticated]) def upload_file(request): """ 通用文件上传接口,将文件上传到OSS 文件保存在 upload/{temporary|permanent}/{date}/{filename} 结构下 需要提供有效的认证令牌 """ try: # 检查是否有文件 if 'file' not in request.FILES: return Response({"error": "No file provided"}, status=status.HTTP_400_BAD_REQUEST) file_obj = request.FILES['file'] # 获取参数 is_permanent = request.data.get('is_permanent', 'false').lower() == 'true' filename = request.data.get('filename', None) # 上传文件 uploader = OSSUploader() result = uploader.upload_file(file_obj, is_permanent, filename) return Response(result, status=status.HTTP_200_OK) except Exception as e: logger.error(f"File upload failed: {str(e)}") return Response( {"error": "File upload failed", "detail": str(e)}, status=status.HTTP_400_BAD_REQUEST )