文件上传,批量处理,防止漏传

73 阅读1分钟
<template>
  <el-upload
    v-model:file-list="fileList"
    :http-request="uploadFile"
    :multiple="true"
    :before-upload="beforeUpload"
    :auto-upload="false"
    list-type="text"
  >
    <el-button type="primary">上传文件</el-button>
    <template #tip>
      <div class="el-upload__tip">
        jpg/png files with a size less than 500KB.
      </div>
    </template>
  </el-upload>
  <el-button type="success" @click="submitUpload">提交</el-button>
</template>

<script setup>
import { ref } from 'vue';
import { ElMessage } from 'element-plus';
import axios from 'axios';

// 存储文件列表
const fileList = ref([]);

// 批量上传函数
const uploadFilesInBatch = async (files) => {
  const batchSize = 5;  // 每次并发上传的数量
  let successCount = 0; // 统计成功上传的文件数量
  let failureCount = 0; // 统计上传失败的文件数量

  for (let i = 0; i < files.length; i += batchSize) {
    const batch = files.slice(i, i + batchSize);
    const results = await Promise.allSettled(batch.map(file => uploadFile({ file })));

    // 根据结果处理成功和失败的计数
    results.forEach(result => {
      if (result.status === 'fulfilled') {
        successCount++;
      } else {
        failureCount++;
      }
    });
  }

  // 显示上传结果
  ElMessage({
    message: `上传完成!成功:${successCount},失败:${failureCount}`,
    type: failureCount > 0 ? 'warning' : 'success',
    duration: 5000,
  });
};

// 提交上传的逻辑
const submitUpload = async () => {
  if (fileList.value.length === 0) {
    ElMessage.warning('没有文件需要上传.');
    return;
  }

  try {
    // 过滤未成功上传的文件
    const filesToUpload = fileList.value.filter(file => file.status !== 'success');
    await uploadFilesInBatch(filesToUpload);
  } catch (error) {
    ElMessage.error('文件上传过程中出现错误.');
  }
};

// 自定义上传文件逻辑
const uploadFile = ({ file }) => {
  return new Promise(async (resolve, reject) => {
    const formData = new FormData();
    formData.append('file', file.raw); // 使用 file.raw 获取原始文件

    try {
      const response = await axios.post('/service/designWorkorder/importByZip', formData, {
        headers: { 'Content-Type': 'multipart/form-data' },
      });

      if (response.status === 200) {
        file.status = 'success'; // 更新文件状态为成功
        resolve();  // 上传成功,调用 resolve
      } else {
        file.status = 'fail'; // 更新文件状态为失败
        reject(new Error(`文件 ${file.name} 上传失败.`));  // 上传失败,调用 reject
      }
    } catch (error) {
      file.status = 'fail'; // 更新文件状态为失败
      reject(error);  // 捕获任何异常,调用 reject
    }
  });
};

// 上传前限制文件类型和大小
const beforeUpload = (file) => {
  const isJPGOrPNG = file.type === 'image/jpeg' || file.type === 'image/png';
  const isLt500KB = file.size / 1024 < 500;

  if (!isJPGOrPNG) {
    ElMessage.error('仅允许上传 JPG/PNG 文件.');
    return false;
  }

  if (!isLt500KB) {
    ElMessage.error('文件大小必须小于 500KB.');
    return false;
  }

  return true;
};
</script>

<style scoped>
.el-upload__tip {
  color: #909399;
  font-size: 12px;
}
</style>