django-11-文件上传

前言:

 

一、文件上传接口管理

POST 文件上传

POST /upload/

Body 请求参数

file: string

请求参数

名称

位置

类型

必选

说明

body

body

object

none

» file

body

string(binary)

上传文件

返回示例

成功

{
  "id": 7,
  "info": [
    "hahaha.sql",
    "D:\\project\\backend\\upload_files\\hahaha.sql",
    "application/octet-stream"
  ]
}

返回结果

状态码

状态码含义

说明

数据模型

201

Created

成功

Inline

返回数据结构

GET 查看文件列表

GET /upload/

Body 请求参数

project: 0

请求参数

名称

位置

类型

必选

说明

body

body

object

none

» project

body

integer

项目id

返回示例

成功

[
  {
    "id": 7,
    "info": [
      "hahaha.sql",
      "D:\\project\\backend\\upload_files\\hahaha.sql",
      "application/octet-stream"
    ]
  },
  {
    "id": 6,
    "info": [
      "blue_activity.sql",
      "D:\\project\\backend\\upload_files\\blue_activity.sql",
      "application/octet-stream"
    ]
  },
  {
    "id": 5,
    "info": [
      "blue_bill.sql",
      "D:\\project\\backend\\upload_files\\blue_bill.sql",
      "application/octet-stream"
    ]
  }
]

返回结果

状态码

状态码含义

说明

数据模型

200

OK

成功

Inline

返回数据结构

DELETE 删除文件

DELETE /upload/{pk}/

请求参数

名称

位置

类型

必选

说明

pk

path

string

none

返回示例

204 Response

{}

返回结果

状态码

状态码含义

说明

数据模型

204

No Content

删除成功

Inline

返回数据结构

GET 查看文件

GET /upload/{pk}/

请求参数

名称

位置

类型

必选

说明

pk

path

string

none

返回示例

成功

{
  "id": 7,
  "info": [
    "hahaha.sql",
    "D:\\project\\backend\\upload_files\\hahaha.sql",
    "application/octet-stream"
  ]
}

返回结果

状态码

状态码含义

说明

数据模型

200

OK

成功

Inline

二、后端代码

https://deepinout.com/django/django-questions/290_django_multiple_file_upload_drf.html

https://www.jianshu.com/p/5e2ce6b5ba5c

2.1 模型

class UploadFile(models.Model):
    """文件上传"""
    file = models.FileField(help_text='文件', verbose_name='文件')
    info = models.JSONField(help_text='数据', verbose_name='数据', default=list, blank=True)

    def __str__(self):
        return self.file.name

    class Meta:
        db_table = 'upload_file'
        verbose_name = '文件上传'
        verbose_name_plural = verbose_name

2.2 序列化器

class UploadFileSerializer(ModelSerializer):
    class Meta:
        model = UploadFile
        fields = '__all__'
        extra_kwargs = {
            'file': {'write_only': True}
        }

# 补充:如果想要设置上传文件的格式或者大小,可以参考以下代码
class UploadFileSerializer(ModelSerializer):
    """
    只能上传表格
    """
    # 限制上传文件的格式
    type_ = ['jpg', 'jpeg']

    def validate(self, attrs):
        attrs = super().validate(attrs)

        file = attrs.get('file')
        
    	# 文件大小不能超过1Mb
        if file.size > 1 * 1000 * 1000:
            raise serializers.ValidationError('文件大小不能超过 1 Mb')
        elif not self.is_filename_match(file.name):
            raise serializers.ValidationError('不支持该文件格式,请上传{}的格式文件'.format([i for i in self.type_]))
        return attrs

    def is_filename_match(self, filename: str):
        # 根据文件名称,判断上传文件的格式
        temp_filename = filename.split('.')
        for i in temp_filename:
            if i in self.type_:
                return True
        return False

    class Meta:
        model = UploadFile
        fields = '__all__'
        extra_kwargs = {
            'file': {
                'write_only': True
            }
        }

2.3 视图

class UploadFileViewSet(ModelViewSet):
    """文件上传"""
    serializer_class = UploadFileSerializer
    queryset = UploadFile.objects.all()

    def perform_create(self, serializer):
        """文件上传,覆写了父类方法"""
        # 过滤一下文件的大小
        name = self.request.data['file'].name
        file_path = str(settings.MEDIA_ROOT / self.request.data['file'].name)
        size = self.request.data['file'].size

        if size > 1024 * 300:
            raise ValidationError('上传失败,文件不能超过300kb!')

        # 文件是否已经存在
        if os.path.isfile(file_path):
            raise ValidationError(f'上传失败,【{name}】已存在')

        # 保存文件
        file_type = self.request.data['file'].content_type
        info = [name, file_path, file_type]

        serializer.save(info=info)

    def destroy(self, request, *args, **kwargs):
        """手动删除文件"""
        file_path = self.get_object().file.path
        os.remove(file_path)  # 删除文件
        return super().destroy(request, *args, **kwargs)

2.4 路由

from rest_framework.routers import DefaultRouter

from .views import TestStepViewSet, UploadFileViewSet

route = DefaultRouter()
route.register('test_steps', TestStepViewSet)
route.register('upload', UploadFileViewSet)

urlpatterns = route.urls

2.5 配置settings.py

# 配置文件上传路径,并在文件目录中创建upload_files目录
MEDIA_ROOT = BASE_DIR / 'upload_files'

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值