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


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

    • 其实就是不要用默认的 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"})
    复制代码

     

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

  • 相关阅读:
    X11 Xlib截屏问题及深入分析二 —— 源码实现1
    堆排序/priority_queue的底层数据结构
    【计网 EMail】计算机网络 EMail协议详解:中科大郑烇老师笔记 (五)
    slint ui学习笔记
    springboot2.1.4.RELEASE 整合 elasticsearch6.8.0
    简单的网页制作期末作业——电影泰坦尼克号(4页)
    【giszz笔记】产品设计标准流程【8】
    算法练习8——有序三元组中的最大值
    MySQL基础(DDL、DML、DQL)
    HTML的实体符号
  • 原文地址:https://www.cnblogs.com/gwt805/p/17955473