本页导航
article
element-plus多文件手动上传
AI摘要
Element Plus 多文件手动上传实现,设置 auto-upload=false 一次性提交多个文件
提示
http-request上传多文件会导致每个文件都会自动上传从而多次请求后端接口,设置auto-upload=false,然后再添加一个上传按钮来请求后端接口,只提交一次上传多个文件,上传成功后清除上传文件列表
接口文件
/**
* 上传多个文件
*/
export function multipartUploadLicense(files: File[], onProgress: (progressEvent: ProgressEvent) => void ): AxiosPromise<FileInfo> {
const formData = new FormData();
files.forEach((file) => {
formData.append('files', file);
});
//@ts-ignore
return request({
url: "/api/license/multipartUpload",
method: "post",
data: formData,
onUploadProgress: onProgress, // 设置上传进度回调
headers: {
"Content-Type": "multipart/form-data",
},
});
}
vue文件
<template>
<div>
<el-upload
ref="uploadRef"
v-model:file-list="fileList"
class="upload-demo"
drag
action=""
accept=".lic, .keystore"
:before-upload="beforeUpload"
:on-change="handleChange"
multiple
:limit="2"
:on-exceed="handleExceed"
:auto-upload=false
style="width: 50%;margin: 20px auto"
>
<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" style="color:red">
只能上传.lic和.keystore等授权文件,不能超过2个,每个大小不超2M
</div>
</template>
</el-upload>
//进度条
<el-progress
v-if="uploading"
:percentage="uploadProgress"
:text-inside="true"
:stroke-width="24"
status="success"
style="width: 80%;margin: 0 auto"
/>
<el-button type="primary" style="width: 300px;margin: 20px auto; display: block" @click="handleUpload">上传授权文件</el-button>
<el-descriptions title="授权文件信息" :column="1" border class="margin-top">
<el-descriptions-item
label="开始时间"
label-align="right"
align="center"
>
<el-tag size="small">{{ LicenseInfo.startTime }} </el-tag>
</el-descriptions-item>
<el-descriptions-item label="结束时间" label-align="right" align="center">
<el-tag size="small">{{ LicenseInfo.endTime }} </el-tag>
</el-descriptions-item>
<el-descriptions-item label="用户数量" label-align="right" align="center">
<el-tag size="small">{{ LicenseInfo.userNum }} </el-tag>
</el-descriptions-item>
<el-descriptions-item label="备注" label-align="right" align="center">
<el-tag size="small">{{ LicenseInfo.remark }} </el-tag>
</el-descriptions-item>
</el-descriptions>
</div>
</template>
<script setup lang="ts">
import { UploadFilled } from '@element-plus/icons-vue'
import { uploadLicense, multipartUploadLicense } from '@/api/file'
import { LicenseControllerService } from "@/generated"
import type { UploadProps, UploadRawFile, UploadUserFile, UploadInstance } from "element-plus";
let uploadRef=ref<UploadInstance>()
const fileList = ref<UploadUserFile[]>([])
const LicenseInfo = ref({
startTime: '',
endTime: '',
userNum: '',
remark: '',
})
// 上传状态和进度
const uploading = ref(false);
const uploadProgress = ref(0);
const handleExceed: UploadProps['onExceed'] = (files) => {
ElMessageBox.alert(`当前限制选择 2 个文件,共选择了 ${files.length} 个文件,请重新选择`);
}
const beforeUpload: UploadProps['beforeUpload'] = (rawFile: UploadRawFile) => {
if (rawFile.size / 1024 / 1024 > 2) {
ElMessage.error('文件大小不能超过2MB')
return false
}
const allowedExtensions = ['.lic', '.keystore']; // 允许的文件类型
const fileExtension = rawFile.name.split('.').pop()?.toLowerCase();
if (!fileExtension || !allowedExtensions.includes(`.${fileExtension}`)) {
ElMessage.error('不支持的文件类型');
return false;
}
return true
}
const handleChange: UploadProps['onChange'] = (uploadFile, uploadFiles) => {
// 将上传的文件添加到 fileList 中
fileList.value = uploadFiles.map(file => file as UploadUserFile);
};
function handleUpload() {
// 提取所有文件的 raw 属性
const files = fileList.value.map(file => file.raw as File);
if(files.length === 0){
ElMessage.error('请选择要上传的授权文件')
return
}
// 上传文件
multipartUploadLicense(files, (event: ProgressEvent) => {
uploading.value = true; // 显示进度条
uploadProgress.value = Math.round(event.loaded / event.total * 100); // 更新进度
//防止进度条的进度和上传的对勾显示时机不一致
if(uploadProgress.value > 98){
uploadProgress.value = 99
}
}).then(() => {
ElMessage({
type: 'success',
message: '上传成功',
grouping: true,
})
uploadRef.value!.clearFiles()
uploadProgress.value = 100;
uploading.value = false; // 隐藏进度条
uploadProgress.value = 0; // 重置进度
loadLicense()
})
}
function loadLicense(){
LicenseControllerService.verifyLicense().then(res => {
if(res.data && res.code === 0){
LicenseInfo.value = res.data as any
}
})
}
onMounted(() => {
loadLicense()
})
</script>
<style scoped>
.margin-top {
width: 80%;
margin: 50px auto;
}
</style>
最后更新于 2026-02-11 18:51