场景
从前端同时上传将多个文件发送到后端API,文件进行大小和后缀名验证。
View
DRF没有支持多文件上传的View,所以需要自定义一个。
这里使用APIView进行继承。
from rest_framework.parsers import MultiPartParser, FormParser
from rest_framework.views import APIView
from rest_framework import status
from .serializers import MultiFileUploadSerializer
class MultiFileUploadView(APIView):
parser_classes = (FormParser, MultiPartParser)
def post(self, request):
fs = MultiFileUploadSerializer(data=request.data)
fs.is_valid(raise_exception=True)
validated_data = fs.validated_data
# 这里可以得到验证后的上传文件
validated_data.get("files")
return Response(status=status.HTTP_200_OK)
Serializer
上面的MultiFileUploadView中使用了MultiFileUploadSerializer,在这里进行定义。
通过ListField的child字段,Serializer可以接收多个文件。
通过validate_files方法验证文件的大小和后缀名。
from rest_framework import serializers
# 单个文件大小上限
SINGLE_FILE_SIZE_LIMIT = 104857600 #100 * 1024 * 1024
# 所有文件大小上限
TOTAL_FILE_SIZE_LIMIT = 104857600 #100 * 1024 * 1024
# 允许使用的后缀名
ALLOWED_FILE_EXTENSIONS = ["png", "mp4"]
class MultiFileUploadSerializer(serializers.Serializer):
files = serializers.ListField(
child=serializers.FileField(required=True, max_length=SINGLE_FILE_SIZE_LIMIT, allow_empty_file=False)
)
def validate_files(self, data):
total_size = 0
# 检查后缀名
for f in data:
extension = f.name.split(".")[-1]
if extension not in ALLOWED_FILE_EXTENSIONS:
raise serializers.ValidationError("无法上传此类文件")
total_size += f.size
# 检查文件大小上限
if total_size > TOTAL_FILE_SIZE_LIMIT:
raise serializers.ValidationError("文件超过100M")
return data
对上传后的文件进行操作
在上面的View中,通过.validated_data.get("files")可以取得验证后的文件列表。
循环文件列表,发现上传后的文件可能是TemporaryUploadedFile或InMemoryUploadedFile类型。对上传的文件可以进行一些操作。
for file in files:
# 取得文件名
file.name
# 取得文件大小
file.size
# 取得content type
file.content_type
# 读取文件
file.file.read()
URL
from django.urls import path
from . import views
urlpatterns = [
path("multi-upload/", views.MultiFileUploadView.as_view(), name="multi-file-upload-view")
]