Vue 自定义点击事件触发文件上传

文件上传组件:UploadFile.vue

<template>
  <div>
    <el-upload
      ref="upload"
      class="upload-demo"
      drag
      multiple
      :http-request="HttpUploadFile"
      :file-list="config.fileList"
      :on-success="handleFileSuccess"
      :on-change="changeFileList"
      :before-remove="fileRemove"
      :accept="config.accept"
      :auto-upload="false"
    >
      <el-icon class="el-icon--upload"><upload-filled /></el-icon>
      <div class="el-upload__text">将文件拖入此处,导入文件</div>
      <div class="el-upload__text">
        <img
          :src="uploadfiletips"
          alt=""
          style="margin-top: 10px; height: 30px"
        />
      </div>
    </el-upload>
    <el-progress class="circle-flag" type="circle" v-if="currentFlag" :percentage="percentage">
      <template #default="{ percentage }">
        <p class="percentage-value">{{ percentage }}%</p>
        <p class="percentage-label">上传进度</p>
      </template>
    </el-progress>
  </div>
</template>

<script setup>
import { ref, defineProps, defineExpose,toRefs,watch } from "vue";
import { UploadFilled } from "@element-plus/icons-vue";
import { ElNotification } from "element-plus";
import uploadfiletips from "@/assets/uploadfiletips.png";
import { uploadFile } from "@/api/upload";
const config = ref({
  // 上传的文件列表
  fileList: [],
  accept: ".txt,.doc,.docx,.pdf,.xps"
});

const emits = defineEmits(["removeFile"])

const props = defineProps({
  fileList: Array,
});

const { fileList } = toRefs(props)

const upload = ref();


watch(()=>fileList.value,(val) => {
  config.value.fileList = []
  if(val.length > 0){
    val.forEach(item => {
      item.name = item.fileName
      config.value.fileList.push(item)
    });
  }
},{immediate: true,deep: true})

//文件上传成功后的钩子函数
const handleFileSuccess = () => {
  
  config.value.fileList = [];
};
//fileList长度改变时触发
const changeFileList = (file, fileList) => {
  
  config.value.fileList = fileList;
  if(fileList.length > 101){
    ElNotification({
      title: "提示",
      message: "文件数量不能超过100个",
      type: "warning",
    });
    config.value.fileList = config.value.fileList.slice(0, 100);
  }
  if(file.size > 1024 * 1024 * 50){
    let message = file.name + "文件大小不能超过50M!"
    ElNotification({
      title: "提示",
      message: message,
      type: "warning",
    });
    config.value.fileList = config.value.fileList.filter(item => item.size <= 1024 * 1024 * 50);
  }
};

const fileRemove = (file) => {
  if(file?.fileId){
    // 删除 编辑 数据库文件
    emits("removeFile",file)
  }
};

// const fileData = ref();
const percentage = ref(0)
const currentFlag = ref(false)
const submitUpload = () => {  
  // 假设你有一个表单的引用(upload.value),但在这里我们不需要提交表单  
  // upload.value.submit(); // 这行代码可能不需要,取决于你的实现  
  
  let promise = new Promise((resolve, reject) => { 
    let newFileList = []
    let oldFileList = []
    config.value.fileList.forEach((item) => {
      if(item?.fileId){
        oldFileList.push(item)
      }
      else{
        newFileList.push(item)
      }
    })
    if (newFileList?.length > 0) {
      currentFlag.value = true
      uploadFile(newFileList,(progress)=>{
        percentage.value = progress
      }).then((res) => {  
        if (res.code === 200) {  
          config.value.fileList = [];  
          const result = parseCustomFilesArray(res.msg);  
          resolve(result); // 解析成功后,通过 resolve 返回结果  
        } else {  
          ElNotification({  
            title: "提示",  
            message: "上传失败",  
            type: "error",  
          });  
          resolve([]); // 即便上传失败,也通过 resolve 返回一个空数组  
        }  
        currentFlag.value = false;
        newFileList = [];
      }).catch((error) => {  
        reject(error); // 如果 uploadFile 抛出错误,通过 reject 拒绝 Promise  
      });  
    } else {  
      resolve([]); // 文件列表为空时,立即解析一个空数组  
    }  
  });  
  
  return promise; // 返回 Promise  
};

const HttpUploadFile = () => {
  // fileData.value.append("files", file.file); // append增加数据
};

function parseCustomFilesArray(data) {  
  // 移除开头和结尾的非法字符(如果有的话)  
  data = data.trim().replace(/^\[|\]$/g, '');  
  
  // 使用正则表达式找到所有的Files(...)部分  
  const filesMatches = data.match(/Files\(([^)]+)\)/g);  
  
  // 初始化结果数组  
  const result = [];  
  
  // 遍历每个匹配项  
  filesMatches?.forEach((match) => {  
    // 移除Files(...)的包装,并分割属性和值  
    const properties = match.slice(6, -1).split(', '); // 移除"Files("和")",并分割属性和值  
  
    // 初始化一个空对象来保存当前文件的属性  
    const file = {};  
  
    // 遍历每个属性和值  
    properties?.forEach((property) => {  
      // 分割属性和值  
      const [key, value] = property.split('=');  
  
      // 去除键和值周围的空白字符,并转换为合适的类型(这里我们假设所有值都是字符串)  
      file[key.trim()] = value.trim();  
    });  
  
    // 将文件对象添加到结果数组中  
    result.push(file);  
  });  
  
  // 假设您有一个名为"Files"的构造函数或类,您可以在这里实例化它  
  // 但由于这里只是一个简单的示例,我们将直接使用普通对象  
  
  // 返回结果数组  
  return result;  
}  
  

defineExpose({ submitUpload });
</script>

<style scoped>
  :deep(.el-upload-dragger){
    height: 160px;
    padding: 0;
  }
  :deep(.el-icon--upload){
    margin: 0;
    padding: 0;
  }
  .circle-flag{
    position: fixed;
    right: 50%;
    top: 50%;
    transform: translate(50%, -50%);
    z-index: 101;
  }
  :deep(.el-upload-list__item){
    border: 1px dotted rgba(0, 34, 102, 0.63);
    border-radius: 10px;
  }
</style>

父组件触发

<upload-file
   ref="uploadRef"
   :fileList="reFileList"
   @removeFile="removeFile"
 />
<el-button type="primary" @click="handleUploadSubmit">
   提 交
</el-button>

const reFileList= ref([]);
const uploadRef = ref(null);

async function handleUploadSubmit(){
    let results = await uploadRef.value.submitUpload();
    console.log(results)
}

文件上传方法处理:upload.js

/*
 * @Author       : Zhao Han(2117961151qq.com)
 * @Version      : V1.0.0
 * @Date         : 2024-06-11 08:55:13
 * @Description  : 仅提供web界面支持文件上传
 */
import { getToken } from "@/utils/auth"
import axios from "axios"

export const uploadFile = async (files, onUploadProgress) => {
  try {
    // let dtoJsonString = JSON.stringify("data")

    let formData = new FormData()

    files.forEach((file) => {
      if (file?.raw) formData.append(`files`, file.raw, file.raw.name);
    })

    // 添加 dtoJson 作为一个字符串字段  
    // formData.append('dtoJson', dtoJsonString); 

    const res = await axios({
      url: process.env.VUE_APP_BASE_URL + '/record/files/test_upload',
      method: 'POST',
      headers: {
        'Authorization': 'Bearer ' + getToken(),
        'Content-Type': 'multipart/form-data'
      },
      onUploadProgress: (progressEvent) => {
        // 计算上传进度
        const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
        // 调用传递给 uploadFile 函数的 onUploadProgress 回调
        onUploadProgress(percentCompleted);
      },
      data: formData
    })
    return res.data
  } catch (error) {
    console.log(error)
  }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值