前言:
一、文件上传接口管理
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 | 成功 | 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 | 成功 | Inline |
返回数据结构
DELETE 删除文件
DELETE /upload/{pk}/
请求参数
名称 | 位置 | 类型 | 必选 | 说明 |
pk | path | string | 是 | none |
返回示例
204 Response
{}
返回结果
状态码 | 状态码含义 | 说明 | 数据模型 |
204 | 删除成功 | 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 | 成功 | 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'