关于文件上传的部分功能

716 阅读3分钟
  1. 实现文件上传显示进度条功能 上传中显示进度条

1719973582943.jpg

上传完成后显示文件列表,进度条隐藏

1719973585646.jpg

主要用到了 :on-change, :before-upload, 另外也可以使用:on-progress,但是不知道为什么这个事件不触发?

image.png

根据索引动态生成 upload ref 的方法

// 使用 ref 创建一个空的对象,用于存储 el-upload 组件的 ref 引用
const uploadRefs = ref<any>({});
// 根据索引动态生成 upload ref 的方法
const getUploadRef = (index: any) => {
  return (el: any) => {
    // 将 el-upload 组件的 ref 引用存储到 uploadRefs 对象中
    uploadRefs.value[index] = el;
  };
};

调用方法:

// 文件上传前的钩子函数,这个时候已经选完文件了
const beforeUpload = (params, index) => {
  // 选完上传的文件,开启进度条
  uploadList[index].isShowJinDuTiao = true;
  uploadList[index].curPercentage = 0;
  uploadList[index].isDisabled = true;
};

// 文件上传中
const handleFileChange = (params, index) => {
  if (params.status == "ready") {
    uploadList[index].isShowJinDuTiao = true;
    uploadList[index].isDisabled = true;
    const interval = setInterval(() => {
      if (uploadList[index].curPercentage >= 100) {
        clearInterval(interval);
        return;
      }

      if (uploadList[index].curPercentage < 99) {
        uploadList[index].curPercentage += 1; //进度条进度
      } else if (uploadList[index].curPercentage == 99) {
        clearInterval(interval);
      }
    }, 30);
  } else if (params.status == "success") {
    uploadList[index].curPercentage = 100;
    uploadList[index].isShowJinDuTiao = false;
    uploadList[index].isDisabled = false;
  }
};
  1. 如果文件上传数量限制为1时,如果想要二次上传文件去覆盖前一个文件 设置 limit 和 on-exceed 可以在选中时自动替换上一个文件。
const handleFileExceed: UploadProps["onExceed"] =
  (index) => (files, fileList) => {
    uploadRefs.value[index]!.clearFiles();
    const file = files[0] as UploadRawFile;
    file.uid = genFileId();
    uploadRefs.value[index]!.handleStart(file);
    uploadRefs.value[index]!.submit();
  };
  1. 文件上传后再移除,fileList对应移除文件
const handleFileUpload = async (params, index) => {
  uploadList[index].fileList = [];
  // fileType:
  // doc 1; pdf 4; zip 5; mater 6; ga 7
  let data: any = await uploadFile(params.file, params.data);
  // 保存文件的 ID 到文件对象的 id 属性中
  params.file.id = data.data.file.id;
  // 添加到文件列表
  uploadList[index].fileList.push(params.file);
};
const handleFileRemove = (file, index) => {
  const fileIndex = uploadList[index].fileList.indexOf(file);
  if (fileIndex !== -1) {
    uploadList[index].fileList.splice(fileIndex, 1);
  }
};

注: el-upload组件中的一些方法,如:on-change方法提供原有的参数:(uploadFile: UploadFile, uploadFiles: UploadFiles,若想要传递额外的参数,要怎么实现呢?

image.png

尝试了两种方法: 第一种 :on-change="handleFileChange(index)"

image.png

第二种: :on-change="(file) => handleFileChange(file, index)"

image.png


文件上传与移除,调用submit提交接口时,需要把fileIds传递给后台,因此用户要知道上传了哪些文件的fileIds,移除了哪些fileIds。 另外,在上传过程中会发现我只上传一个文件,但会在文件列表中出现两个一样的文件

image.png

看文档 on-change不止在添加文件的时候触发 文件状态改变时的钩子,添加文件、上传成功和上传失败时都会被调用,因此要改成只在添加文件时触发

:on-remove="handleFileRemove" :on-change="handleFileChange"

99d456de57f8cdaef4d438fcd70e94e.png

代码记录: el-upload组件

 <el-upload
                      :http-request="uploadFile"
                      class="upload-demo"
                      v-model:file-list="fileList"
                      :on-progress="handleProgress"
                      :on-success="handleFileSuccess"
                      :before-remove="beforeFileRemove"
                      :on-remove="handleFileRemove"
                      :on-change="handleFileChange"
                    >
                      <el-button type="primary">Click to upload</el-button>
                      <template #tip>
                        <div class="el-upload__tip">
                          .doc, .zip, .docx, .pdf, .gif, .txt, .jpg, .jpeg, .png
                          files with a size less than 30mb.
                        </div>
                      </template>
                    </el-upload>

点击上传按钮

/**
 * 自定义图片上传
 * @param options
 */
async function uploadFile(options: UploadRequestOptions): Promise<any> {
  const { data } = await discussionUpload(options.file);
  // 保存文件的 ID 到文件对象的 id 属性中
  options.file.id = data.content.fileId;


  // 不要在这里处理fileId,否则文件移除时,获取到的fileId对应不上,除非没有移除文件功能
  // ruleForm.fileId.push(data.content.fileId);
}

移除前事件

const beforeFileRemove = (uploadFile, uploadFiles) => {
  return ElMessageBox.confirm(
    `Cancel the transfer of ${uploadFile.name} ?`
  ).then(
    () => true,
    () => false
  );
};

文件改变

const handleFileChange = (file, fileList) => {
  // on-change只在添加文件触发: file.status === "ready"
  if (file.status === "ready") {
    fileList.vlaue?.push(file);
    isFinished.value = false;
  }
};

文件移除

const handleFileRemove = (file, fileList) => {
  if (fileList.value && fileList.value.length > 0) {
    fileList.value.splice(fileList.value.indexOf(file), 1);
  }
};

点击submit提交数据

const submitForm = async (formEl: FormInstance | undefined) => {
  ruleForm.aid = props.id;
  ruleForm.discussionType = props.type;
  ruleForm.fileId = [];
  if (!formEl) return;

  let targetFlag = fileList.value.every((item) => item.status === "success");

  if (fileList.value.length > 0) {
    if (!(targetFlag && isFinished.value)) {
      return ElMessage({
        type: "error",
        message: "The file is uploading, please operate later",
      });
    }
  }


// 重点,要在这里拼接fileId给后台
  fileList.value &&
    fileList.value.forEach((ele) => {
      ruleForm.fileId.push(ele.raw.id);
    });

  await formEl.validate((valid, fields) => {
    if (valid) {
      saveDiscussion(ruleForm).then((res) => {
        ElMessage({
          message: res.message,
          type: "success",
        });
        ruleFormRef.value.resetFields();
        emit("dialogStatus", { show: false });
        emit("uploadData");
      });
    } else {
      console.log("error submit!", fields);
    }
  });
};