Vue3+Ant Design Vue 实现手动异步文件上传(含大小校验、弹窗上传)

需求:选择需要上传的文件后阻止默认上传,在点击弹窗的确认按钮后触发上传文件事件。

模板部分(上传弹窗+上传组件)

html 复制代码
<template>
  <!-- 上传文件按钮 -->
  <a-button type="primary" @click="handleUpload">
    <upload-outlined />
    上传文件
  </a-button>

  <!-- 上传文件弹窗 -->
  <a-modal
    v-model:visible="uploadModalVisible"
    title="上传文件"
    :confirm-loading="uploading"
    @ok="handleUploadOk"
    @cancel="handleUploadCancel"
  >
    <a-upload
      v-model:file-list="fileList"
      :before-upload="beforeUpload"
      :max-count="1"
      @remove="handleRemoveFile"
    >
      <a-button>
        <upload-outlined />
        选择文件
      </a-button>
    </a-upload>
  </a-modal>
</template>

JS 逻辑(核心异步上传逻辑)

基于 Vue3 setup 语法,封装所有上传核心逻辑,包含状态定义、校验、请求、状态重置:

javascript 复制代码
import { ref } from 'vue';
import { message } from 'ant-design-vue';
import { UploadOutlined } from '@ant-design/icons-vue';
// 后端文件上传接口
import { FileApi } from '@/api/fileApi';

export default {
  name: 'FileUpload',
  components: {
    UploadOutlined
  },
  setup() {
    // 弹窗显示状态
    const uploadModalVisible = ref(false);
    // 选中的文件列表
    const fileList = ref([]);
    // 上传加载状态
    const uploading = ref(false);

    // 打开上传弹窗
    const handleUpload = () => {
      uploadModalVisible.value = true;
    };

    /**
     * 上传前文件校验
     * @param {File} file - 选中的文件对象
     * @returns {boolean} 阻止/允许上传
     */
    const beforeUpload = (file) => {
      // 限制文件大小10MB
      const isLt10M = file.size / 1024 / 1024 < 10;
      if (!isLt10M) {
        message.error('文件大小不能超过 10MB');
      }
      // 返回false 阻止组件自动上传,实现手动上传
      return false;
    };

    // 手动移除已选文件
    const handleRemoveFile = () => {
      fileList.value = [];
    };

    /**
     * 确认上传(核心异步上传方法)
     */
    const handleUploadOk = async () => {
      // 未选择文件校验
      if (fileList.value.length === 0) {
        message.warning('请选择要上传的文件');
        return;
      }

      // 开启加载状态
      uploading.value = true;
      try {
        // 组装FormData文件参数
        const formData = new FormData();
        // 获取原生文件对象,塞入表单
        formData.append('file', fileList.value[0].originFileObj);

        // 调用后端上传接口,异步请求
        const res = await FileApi.uploadFile(formData);

        if (res.success) {
          message.success('文件上传成功');
          // 关闭弹窗、清空文件列表
          uploadModalVisible.value = false;
          fileList.value = [];
          // 可在此处调用刷新列表方法,更新数据
          // await fetchData();
        } else {
          message.error(res.message || '文件上传失败');
        }
      } catch (error) {
        // 捕获接口异常、网络异常
        message.error('文件上传失败,网络异常');
        console.error('文件上传错误:', error);
      } finally {
        // 关闭加载状态
        uploading.value = false;
      }
    };

    // 取消上传,重置状态
    const handleUploadCancel = () => {
      uploadModalVisible.value = false;
      fileList.value = [];
    };

    return {
      uploadModalVisible,
      fileList,
      uploading,
      handleUpload,
      beforeUpload,
      handleUploadOk,
      handleUploadCancel,
      handleRemoveFile
    };
  }
};

常见踩坑问题总结

问题1:文件选择后自动上传,无法手动控制

解决方案:before-upload 钩子必须返回 false,缺一不可。

问题2:后端接收不到文件

解决方案:必须使用 originFileObj 获取原生文件,不要直接传递 fileList 中的对象。

问题3:上传过程中重复点击提交

解决方案:绑定confirm-loading 状态,上传期间禁用按钮。

问题4:上次上传文件残留,二次上传无需选文件直接提交

解决方案:弹窗关闭、上传成功、移除文件时,手动清空 fileList。

相关推荐
Maxkim12 小时前
私钥就是数字 4:扒一扒这场把一家 CA 直接送走的事故
javascript·架构
gCode Teacher 格码致知12 小时前
前端教学8:提高 CSS 选择器的优先级,有哪些方法?
前端·css·html5
u01110267512 小时前
Canvas 导出 PNG 时 quality 参数为什么不起作用
前端·javascript·vue.js
众链网络12 小时前
年卡跨淡旺季的有效期模型:不可用日期、次数与顺延规则
java·前端·数据库
2601_9498477512 小时前
jose 跨端三方库仓颉适配全流程
前端·javascript·flutter
CappuccinoRose13 小时前
滚动交互体系
前端·javascript·交互·html5·1024程序员节
时空节拍AI数字人13 小时前
博物馆数字人讲解系统设计:知识库 schema、展项联动协议与时序控制
java·服务器·前端·人工智能·ai·语音识别
吴建旭 智宅焕13 小时前
智能家居全国交付中前端工具与后端基础设施的系统集成架构:报价入口与交付兜底的闭环设计
前端·架构·智能家居
开开心心就好13 小时前
电脑小说阅读器,支持朗读和自定义皮肤
服务器·开发语言·javascript·算法·pdf·c#·音视频
夏天要喝冰可乐13 小时前
Codex 写 Three.js 大屏实录:800 行代码,和一条画反的弧线
前端·aigc