一、需求描述
在 Vue3 项目中使用 Element Plus 封装上传组件。限制上传文件的大小、实现拖拽上传、限制文件只能上传一个,再次上传则覆盖原来的文件
二、实现效果
三、源码
我的技术栈:Vue3 + Ts + Vite + Element Plus
<template>
<el-upload
class="upload-demo"
drag
ref="upload"
action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"
:limit="1"
:on-exceed="handleExceed"
:auto-upload="false"
:on-change="handleChangeFile"
>
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<template #tip>
<div class="el-upload__tip"> 只能上传一个文件,文件大小不超过3M </div>
</template>
</el-upload>
<el-button class="ml-3" type="success" @click="submitUpload"> upload to server </el-button>
</template>
<script setup lang="ts">
import {
UploadFilled } from '@element-plus/icons-vue'
import {
ElMessage, ElMessageBox, genFileId } from 'element-plus'
import type {
UploadInstance, UploadProps, UploadRawFile } from 'element-plus'
import {
ref } from 'vue'
const upload = ref<UploadInstance>()
/**
* 校验文件上传大小,若还需校验文件格式,请自行增加代码
*/
const handleChangeFile = (file: any, fileList: any) => {
if (!file) return
//限制上传文件大小
const fileSize = file.size / 1024 / 1024
if (fileSize > 3) {
const currIdx = fileList.indexOf(file)
fileList.splice(currIdx, 1)
ElMessage.warning('上传文件大小不能超过 3MB!')
}
}
/**
* 限制只能上传一个文件,再次上传则覆盖之前的文件
*/
const handleExceed: UploadProps['onExceed'] = (files) => {
ElMessageBox.confirm('重复上传会覆盖之前的材料,是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
{
const file = files[0] as UploadRawFile // 拿到第二次上传的文件
const fileSize = file.size / 1024 / 1024 // 获取改文件的文件大小
if (fileSize < 3) {
// 文件大小复符合规则,将上一个文件清空,将新文件上传进行覆盖
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
upload.value!.clearFiles()
file.uid = genFileId()
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
upload.value!.handleStart(file)
ElMessage({
type: 'success',
message: '覆盖成功'
})
} else {
ElMessage.warning('上传文件大小不能超过 3MB!')
}
}
})
.catch(() => {
// ElMessage({
// type: 'info',
// message: 'Delete canceled'
// })
})
}
/**
* 手动上传方法(因为我需要手动上传,所以将 auto-upload 设置为了false )
*/
const submitUpload = () => {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
upload.value!.submit()
}
</script>
<style lang="scss" scoped>
.upload-demo {
width: 100%;
}
</style>
</style>