vue3 + element-plus 的 upload + axios + django 文件上传并保存

发布时间 2024-01-09 22:24:45作者: 卫龙吖

之前在网上搜了好多教程,一直没有找到合适自己的,要么只有前端部分没有后端,要么就是写的不是很明白。所以还得靠自己摸索出来后,来此记录一下整个过程。

  • 其实就是不要用默认的 action,要手动实现上传方式 http-request,然后再传给后端进行各种操作了
    • 这里隐藏了文件展示列表
    • 展示了上传文件的个数
    • 文件去重上传
    • 也对上传文件的格式做了限制
    • 在点击创建的时候 progress 会随着上传进度动态变化

环境安装什么的就不讲了,直接上代码好吧,这个是样式图

 

这是vue3代码

 1 <template>
 2   <el-upload class="upload-demo form-item" v-model:file-list="fileList" drag multiple :http-request="httpRequest" :show-file-list="false" auto-upload="false" :accept=upload_accept>
 3       <el-icon class="el-icon--upload"><upload-filled /></el-icon>
 4       <div class="el-upload__text">拖拽 / 点击上传文件 ( zip, jpg, png ……)</div>
 5       <template #tip>
 6           <div class="el-upload__tip">已上传 {{ fileListLength }} 个文件</div>
 7       </template>
 8   </el-upload>
 9   <el-progress :percentage="progress.curr" :color="progress.color" />
10   <el-button type="info" class="btn" @click="removeFile">清空文件</el-button>
11   <el-button type="primary" class="btn" @click="create">创建</el-button>
12 </template>
13 
14 <script setup lang="ts">
15 import { ref, watch } from "vue";
16 import http from "@/utils/axios/index";
17 import { UploadFilled } from '@element-plus/icons-vue';
18 import { ElMessage } from 'element-plus';
19 
20 
21 const public_elmsg_success = (msg: string) => {
22   ElMessage({ type: 'success', duration: 1000, showClose: true, message: msg })
23 };
24 
25 const public_elmsg_warning = (msg: string) => {
26   ElMessage({ type: 'warning', duration: 1000, showClose: true, message: msg })
27 };
28 
29 const public_elmsg_error = (msg: string) => {
30   ElMessage({ type: 'error', duration: 1000, showClose: true, message: msg })
31 };
32 
33 const upload_accept = ref(".JPG,.PNG,.JPEG,.PCD,.MP4,.AVI,.DAT,.DVR,.VCD,.MOV,.SVCD,.VOB,.DVD,.DVTR,.DVR,.BBC,.EVD,.FLV,.RMVB,.WMV,.MKV,.3GP,.ZIP"); // 限制了上传文件的格式 大写后缀
34 const upload_lower = ref(upload_accept.value.split(',').map((item: any) => item.toLowerCase())); // 限制上传文件的格式 小写后缀
35 const fileList: any = ref([]);
36 const fileList1: any = ref([]);
37 const fileListLength = ref(0);
38 
39 const progress = ref({ "curr": 0, "color": "orange" })
40 
41 
42 watch(fileList1, (newVal, oldVal) => {
43   console.log(newVal, oldVal)
44   fileListLength.value = newVal.value;
45   fileListLength.value = newVal.length;
46 }, { immediate: true, deep: true });
47 
48 const httpRequest = (options: any) => {
49   let nameList: Array<any> = [];
50   fileList1.value.forEach((item: any) => {
51       nameList.push(item.name);
52   });
53   const file_suffix = options.file.name.split(".");
54   if (!upload_lower.value.includes(`.${file_suffix[file_suffix.length - 1]}`)) {
55       public_elmsg_warning(`文件 ${options.file.name} 格式不正确`);
56       return;
57   }
58   if (nameList.includes(options.file.name)) { }
59   else {
60       fileList1.value.push(options.file)
61   }
62   fileList.value = fileList1.value;
63 }
64 
65 const removeFile = () => {
66   fileList.value = [];
67   fileList1.value = [];
68   progress.value.curr = 0;
69 }
70 
71 
72 const create = () => {
73   const formData = new FormData()
74   fileList1.value.forEach((file: any) => {
75       console.log(file)
76       formData.append('files', file)
77   })
78 
79   http.post("task/create/", formData, {
80       headers: { "Content-Type": "multipart/form-data" }, onUploadProgress(progressEvent: any) {
81           progress.value.curr = Math.round((progressEvent.loaded * 100) / progressEvent.total)
82           if (progress.value.curr == 100) { progress.value.color = 'green' }
83           else { progress.value.color = 'orange' }
84       },
85   }).then((res: any) => {
86       if (res.code == 0) {
87           public_elmsg_success("任务创建成功")
88       }
89       else { public_elmsg_error(res.msg) }
90   }
91   );
92 }
93 </script>

v3版本的 djagno 代码 

 1 from loguru import logger 2 from django.http.response import JsonResponse 3 from django.views.decorators.csrf import csrf_exempt 4 
 5 @csrf_exempt 6 def create_task(request):
 7     files = request.FILES.getlist('files')
 8     for fit in files:
 9         logger.info(f"name: {fit.name} size: {round(fit.size/ 1024 / 1024 / 1024, 5)} G")
10         # 保存文件
11         #  with open(f"{os.sep.join(['.', fit['name']])}", mode="wb") as f:  
12         #         f.write(fit)
13 
14     return JsonResponse({"code": 0, "msg": "success"})

还有什么更好的方法 ,欢迎大家讨论哇