ant design vue 上传文件自定义上传,并发上传文件、取消上传、重新上传

ant design vue 上传文件组件

<a-upload-dragger
   v-model:fileList="fileList"
   :accept="accept"
   :beforeUpload="beforeUploadFile"
   class="upload-btn"
   :headers="headers"
   multiple
   @change="handleChange"
>
   <button v-if="!showUploadFiles" class="submitbtn">点击上传</button>
   <button v-else class="submitbtn">继续上传</button>
</a-upload-dragger>
<div v-else class="file-list">
  <div class="file-item" v-for="(item,index) in uploadFileList" :key="index">
    <span class="fileName">{{ item.file?.name}}</span>
    <span class="fileSize">{{ sizeCompt(item.file?.size) || 0 }}</span>
    <span :class="{'error-statue':item.status=='error','loading-status':item.status=='uploading'}">{{ item.status=='error'?'上传失败,请重试' : item.status=='uploading'?'上传中':''}}</span>
    <div class="svg" v-show="item.status=='uploading'">
        <img src="@/assets/images/uploading.gif" alt="">
    </div>
    <div class="svg">
        <svg xmlns="http://www.w3.org/2000/svg" v-if="item.status=='done'" viewBox="0 0 18 18" fill="none">
            <image href="@/assets/images/svg/uploadSuccess.svg" x="0" y="0"/>
        </svg>
        <svg xmlns="http://www.w3.org/2000/svg" v-else-if="item.status=='error'" viewBox="0 0 18 18" fill="none" @click="reupload(item)">
            <image href="@/assets/images/svg/reupload.svg" x="0" y="0"/>
        </svg>
        <svg xmlns="http://www.w3.org/2000/svg" v-else viewBox="0 0 18 18" fill="none" @click="cancelUpload(item)">
            <image href="@/assets/images/svg/cancelUpload.svg" x="0" y="0"/>
        </svg>
      </div>
  </div>
  // 上传文件部分
  const accept = ref(
    ".ppt,.pps,.jpeg,.jfif, .pot, .ppa,.pptx,.ppsx,.potx,.doc,.docx,.docm,.dot,.docx,.xlsx,.xls,.csv,.xlsb,.xltx,.xltm,.xlam,.mp4,.flv,.f4v,.webm,.mpeg,.mov,.wmv,.pdf,.txt,.zip,.rar,.7z,.tar,.gz,.tiff,.png,.psd,.raw,.svg,.eps,.jpg,.raw,.ai,.gif"
  );
  //文件列表
  const fileList = ref([]);
  //请求头
  const headers = {
    token: ls.get("token"),
    "content-type": "multipart/form-data",
  };

上传文件前操作

  // 上传文件之前的钩子,参数为上传的文件
  const beforeUploadFile = (file, fileLists) => {
    console.log("拿到的文件列表", file, fileList.value);
    //判断文件大小是否超过剩余空间
    // if(file.size>diskData.value.free){
    //     message.warning('您的存储空间不足')
    //     return false
    // }
    // 限制文件类型
    // const fileNames = file.name.split('.')
    // const fileType = fileNames[fileNames.length - 1].toLocaleLowerCase()
    // const extList = ['jpg','jpeg', 'png', 'gif','ppt','word','excel','mp4','pdf','txt','doc','docx','zip','exe','bat','vbs']
    // if (!extList.find((item) => item == fileType)) {
    //   this_.$message.error('不能上传.'+fileType+'类型的文件!')
    //   return false
    // }
    // console.log(888)
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(() => {
      uploadFiles(fileLists);
    }, 500);
    return false;
  };

上传文件列表时:使用防抖避免重复调用上传函数

并发请求

// 并发请求
const concurrency = async (promiseList, max) => {
  let index = 0;
  const results = new Array(promiseList.length);
  const executing = [];
  const runCurrency = async () => {
    if (index == promiseList.length) {
      return;
    }
    const currencyIndex = index++;
    const currency = promiseList[currencyIndex];
    const p = currency()
      .then((result) => {
        results[currencyIndex] = result;
        executing.splice(executing.indexOf(p), 1);
      })
      .catch((error) => {
        results[currencyIndex] = error;
        executing.splice(executing.indexOf(p), 1);
      });
    executing.push(p);
    let r = Promise.resolve;
    if (executing.length >= max) {
      r = Promise.race(executing);
    }
    await r;
    await runCurrency();
  };
  await runCurrency();
  await Promise.all(executing);
  getDiskFileList();
  return results;
};
详细解析
  • index:用于跟踪当前处理的 promise 索引。
  • results:存储每个 promise 的结果。
  • executing:用于跟踪当前正在执行的 promise。
runCurrency 函数
  • 如果所有 promise 都已执行完毕,则返回。
  • 否则,获取当前的 promise,并将其执行。
  • 使用 Promise.race 控制并发,确保同时只执行 max 个 promise。
  • 递归调用 runCurrency 以处理下一个 promise。

上传函数

// 上传函数
const uploadFiles = async (fileLists) => {
  fileList.value = fileLists.map((item, index) => {
    const { uid } = item;
    return {
      uid,
      file: item,
      status: "init",
    };
  });
  showUploadFiles.value = true;
  uploadFileList.value.push(...fileList.value);
  console.log(2345, uploadFileList.value, fileList.value);
  const promitList = uploadFileList.value.map((item) => {
    return async () => {
      // 限制文件类型
      const fileNames = item.file?.name.split(".");
      const fileType =
        fileNames[fileNames.length - 1].toLocaleLowerCase();
      const extList = [
        "tiff",
        "jpeg",
        "jfif",
        "png",
        "psd",
        "raw",
        "svg",
        "eps",
        "jpg",
        "raw",
        "ai",
        "gif",
        "ppt",
        "pps",
        "pot",
        "ppa",
        "pptx",
        "ppsx",
        "potx",
        "doc",
        "docx",
        "docm",
        "dot",
        "dotx",
        "xlsx",
        "xls",
        "csv",
        "xlsb",
        "xltx",
        "xltm",
        "xlam",
        "mp4",
        "flv",
        "f4v",
        "webm",
        "mpeg",
        "mov",
        "wmv",
        "mp3",
        "wma",
        "wav",
        "ape",
        "flac",
        "ogg",
        "aac",
        "pdf",
        "txt",
        "zip",
        "rar",
        "7z",
        "tar",
        "gz",
      ];
      if (!extList.find((item) => item == fileType)) {
        item.status = "wrong";
        return false;
      }
      const formData = new FormData();
      formData.append("files", item.file);
      item.status = "uploading";
      console.log(formData, item.file);
      try {
        await requploadFiles(window, item.uid, formData);
        item.status = "done";
        diskStore.getGroup();
        getDiskFileList();
        diskStore.getDiskMemory();
      } catch (error) {
        message.error(error.message);
        item.status = "error";
      }
      // uploadFileList.value=uploadFileList.value.map((i)=>{
      //     if(i.uid==item.uid){
      //         i.status=item.status
      //     }
      //     return item
      // })
      // console.log('after',uploadFileList.value)
      // uploadFileList.value=uploadFileList.value.filter((fileItem)=>fileItem.uid!=item.uid)
      // console.log('before',uploadFileList.value)
    };
  });
  concurrency(promitList, 6);
};
详细解析
  • fileList.value:将传入的文件列表映射为具有 uidfile 和 status 属性的对象数组。
  • showUploadFiles.value:显示上传文件的状态。
  • promitList:存储每个文件的上传逻辑,返回一个 async 函数。
文件类型检查和上传
  • 检查文件类型是否在允许的扩展名列表中。
  • 使用 FormData 构造上传请求的主体。
  • 根据上传结果更新文件的状态,并在上传成功或失败时进行相应的处理

重新上传

// 重新上传
const reupload = async (item) => {
  console.log("reupload");
  const formData = new FormData();
  formData.append("files", item.file);
  uploadFileList.value.map((i) => {
    if (i.uid == item.uid) {
      i.status = "uploading";
    }
  });
  try {
    await requploadFiles(window, item.uid, formData);
    uploadFileList.value.map((i) => {
      if (i.uid == item.uid) {
        i.status = "done";
      }
    });
    diskStore.getGroup();
    getDiskFileList();
    diskStore.getDiskMemory();
  } catch (error) {
    message.error(error.message);
    uploadFileList.value.map((i) => {
      if (i.uid == item.uid) {
        i.status = "error";
      }
    });
  }
};

取消上传

// 取消上传
const cancelUpload = (item) => {
  console.log("cancle");
  if (typeof window?.[item.uid] === "function") {
    window?.[item.uid]("请求中断");
  }
};

文件状态回调

// 文件状态改变的回调——上传中、完成、失败都会调用这个函数。
const handleChange = (info) => {
  if (info.file.status !== "uploading") {
    console.log(info.file, info.fileList);
  }
  if (info.file.status === "done") {
    message.success(`${info.file.name} file uploaded successfully`);
    // diskStore.getDiskMemory()
  } else if (info.file.status === "error") {
    message.error(`${info.file.name} file upload failed.`);
  }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/873029.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Redis 事务:支持回滚吗?深入解析

今天我们要来探讨一个关于 Redis 事务的重要问题&#xff1a;Redis 事务支持回滚吗&#xff1f;这个问题在 Redis 的使用中经常被提及&#xff0c;对于正确理解和使用 Redis 事务至关重要。那么&#xff0c;让我们一起深入解析这个问题吧&#xff01; 一、Redis 事务简介 在了…

tabBar设置底部菜单选项以及iconfont图标

tabBartabBar属性:设置底部 tab 的表现 ​ ​ ​ ​ 首先在pages.json页面写一个tabBar对象,里面放入list对象数组,里面至少要有2个、最多5个 tab, 如果只有一个tab的话,H5(浏览器)依然可以显示底部有一个导航栏,如果没有,需要重启后才有,小程序则报错,只有2个以上才可以…

IDEA加载工程报错Error Loading Project: Cannot load module demo.iml解决

spring boot工程由于工程名字为demo不太好&#xff0c;直接更改了这个工程的名字&#xff0c;主要操作了包括重命名项目文件夹、修改IDEA中的项目名称、模块名称、包名称、以及相关的配置文件等。 然后再打开工程&#xff0c;报错Error Loading Project: Cannot load module de…

瑜伽馆预约系统小程序搭建,全民健身下的市场机遇

随着现代生活水平的提高&#xff0c;人们对健康的要求逐渐提高&#xff0c;瑜伽作为一种修身养性的健身方式&#xff0c;深受大众欢迎。在互联网小程序的普及下&#xff0c;瑜伽馆预约小程序也成为了市场的必然发展趋势&#xff01; 为什么要开发瑜伽馆预约系统&#xff1f; 瑜…

今天又学到了——图编号关联章节号,QGIS下载文件存储的瓦片

记录教程来源&#xff1a;​​​​​​【Word图编号关联章节号】图片分章节 编号&#xff0c;图1-1、图2-1_哔哩哔哩_bilibili 上面链接这个实现的是这个效果&#xff1a; word自动目录及章节自动编号教程_哔哩哔哩_bilibili&#xff0c;这个的效果是自己设计多级列表&#xf…

Redis高级-----持久化AOF、RDB原理

目前已更新系列&#xff1a; 当前&#xff1a;Redis高级-----持久化AOF、RDB原理 Redis高级---面试总结5种数据结构的底层实现 Redis高级----主从、哨兵、分片、脑裂原理-CSDN博客 Redis高级---面试总结内存过期策略及其淘汰策略 计算机网络--面试知识总结一 计算机网络-…

《JavaEE进阶》----11.<SpringIOCDI【Spring容器+IOC详解+DI介绍】>

本篇博客会详细讲解什么是Spring。 SpringIOC SpringID 五个类注解&#xff1a;Controller、Service、Repository、Component、Configuration 一个方法注解&#xff1a;Bean 什么是Spring IOC容器 Spring 是包含众多工具的IOC容器。能装东西的容器。 1.容器 如我们之前学的 Tom…

JavaFX基本控件-TextField

JavaFX基本控件-TextField 常用属性textpromptTextpaddingalignmentwidthheighttooltipbordereditabledisablevisible 格式化整形格式化 实现方式Java实现fxml实现 常用属性 text 设置文本内容 textField.setText("测试数据");promptText 设置文本字段的提示文本&am…

Ollama—87.4k star 的开源大模型服务框架!!

这一年来&#xff0c;AI 发展的越来越快&#xff0c;大模型使用的门槛也越来越低&#xff0c;每个人都可以在自己的本地运行大模型。今天再给大家介绍一个最厉害的开源大模型服务框架——ollama。 项目介绍 Ollama 是一个开源的大语言模型&#xff08;LLM&#xff09;服务工具…

替换Windows AD时,网络准入场景如何迁移对接国产身份域管?

Windows AD是迄今为止身份管理和访问控制领域的最佳实践&#xff0c;全球约90%的中大型企业采用AD作为底层数字身份基础设施&#xff0c;管理组织、用户、应用、网络、终端等IT资源。但随着信创建设在党政机关、金融、央国企、电力等各行各业铺开&#xff0c;对Windows AD域的替…

swagger简单使用学习

注意 一下基于spring-boot 3.0.2版本&#xff0c;该版本不支持springfox-swagger2 2.9.2会报错&#xff0c;无法访问swagger 安装 在pomx文件中添加对应的依赖 <!-- swagger --><dependency><groupId>org.springdoc</groupId><artifactId>spr…

Superset二次开发之Select 筛选器源码分析

路径&#xff1a;superset-frontend/src/filters/components/Select 源码文件&#xff1a; 功能点&#xff1a; 作用 交互 功能 index.ts作为模块的入口点,导出其他文件中定义的主要组件和函数。它使其他文件中的导出可以被外部模块使用。 SelectFilterPlugin.tsx 定义主要…

PostgreSQL的repmgr工具介绍

PostgreSQL的repmgr工具介绍 repmgr&#xff08;Replication Manager&#xff09;是一个专为 PostgreSQL 设计的开源工具&#xff0c;用于管理和监控 PostgreSQL 的流复制及实现高可用性。它提供了一组工具和实用程序&#xff0c;简化了 PostgreSQL 复制集群的配置、维护和故障…

python的sqlalchemy使用@contextmanager来定义上下文管理器

Python通过函数名调用函数的几种场景 华为或超聚变服务器安装linux 你知道":“和”//"在python里面代表什么吗&#xff1f;这篇《python运算符》介绍&#xff0c;你肯定不想错过 SQLAlchemy通过contextmanager简化回滚操作 如何理解python的sqlalchemy这种orm框架&am…

大数据采集与分析实训室解决方案

随着信息技术的飞速发展&#xff0c;大数据已成为推动产业升级、社会进步的重要力量。为了培养适应未来社会需求的大数据专业人才&#xff0c;构建一套科学、先进的大数据采集与分析实训室解决方案显得尤为重要。为此&#xff0c;唯众特推出全面升级的大数据采集与分析实训室解…

Java项目——苍穹外卖(一)

Entity、DTO、VO Entity&#xff08;实体&#xff09; Entity 是表示数据库表的对象&#xff0c;通常对应数据库中的一行数据。它通常包含与数据库表对应的字段&#xff0c;并可能包含一些业务逻辑。 DTO&#xff08;数据传输对象&#xff09; 作用&#xff1a;DTO 是用于在…

Leetcode Hot 100刷题记录 -Day10(合并区间)

合并区间 问题描述&#xff1a; 以数组 intervals 表示若干个区间的集合&#xff0c;其中单个区间为 intervals[i] [starti,endi] 。请你合并所有重叠的区间&#xff0c;并返回 一个不重叠的区间数组&#xff0c;该数组需恰好覆盖输入中的所有区间 。 示例 1&#xff1a; 输入&…

Netty系列-3 ChannelFuture和ChannelPromise介绍

背景 Netty源码中大量使用了Future和Promise&#xff0c;学习ChannelFuture和ChannelFuture有助于理解Netty的设计思路。 本文的重点内容在于梳理清楚这些类的关系以及结合源码实现介绍这些类的作用&#xff0c;其中核心逻辑在于DefaultPromise和DefaultChannelPromise&#x…

UnLua环境搭建

一、环境搭建 1、下载UnLua工程&#xff1a;https://github.com/Tencent/UnLua 2、复制Plugins/UnLua目录下的插件到自己的项目中 3、重新生成自己的VS工程 4、打开VS工程的项目名.Build.cs文件&#xff0c;引用UnLua插件,重新编译工程 PublicDependencyModuleNames.AddRan…

Post-Training有多重要?一文带你了解全部细节

1. 简介 随着LLM学界和工业界日新月异的发展&#xff0c;不仅预训练所用的算力和数据正在疯狂内卷&#xff0c;后训练&#xff08;post-training&#xff09;的对齐和微调方法也在不断更新。InstructGPT、WebGPT等较早发布的模型使用标准RLHF方法&#xff0c;其中的数据管理风…