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.`);
  }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值