原因:我并没有用el-upload上面的action设置上传url,也没有用他自带的方法上传
这里我使用的是通过自定义接口手动上传,即点击外部按钮,将文件转换后调用接口将文件传参,拿到存储后转换回来的文件url,直接调用接口上传,没有用到action,以及upload上的submit方法等
自定义接口上传文件
<el-upload :auto-upload="false" accept=".mp4,.avi,.mp3,.png,.jpg,.jpeg,.gif,.bmp,.webp,.svg" drag
v-model:file-list="fileList" :on-preview="handlePictureCardPreview" ref="upload" :on-progress="handleProgress">
<div class="el-upload__text">
拖拽文件到这里 或者 <em>点击选择文件</em>
</div>
</el-upload>
<el-button @click='sureUpload'>上传</el-button>
methods:{
sureUpload(){
for (const file of this.fileList) {
if (file.status !== 'ready') {
continue
}
let res = await this.uploadEleFile(file)
if (res) {
file.url = res.link
file.name=res.originalName
}
}
},
uploadEleFile(file){
const formData = new FormData();
formData.append('file', file.raw);
return new Promise(async (resolve,reject)=>{
let res;
try {
res = await axios.post(baseUrl + '/form/material/upload', formData, {
headers: {
'Authorization': userStore.token,
// 不要手动设置 Content-Type,Axios 会自动处理
//'Content-Type': 'multipart/form-data'
},
// 监听上传进度
onUploadProgress: (progressEvent) => {
if (progressEvent.progress) {
const percentCompleted = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
);
// 更新进度
file.percentage = percentCompleted;
// console.log(`Upload progress: ${percentCompleted}%`);
}
},
});
if(res.status===200){
file.status = 'success'
resolve(res.data.data)
}
} catch (error) {
file.status = 'fail'
this.$message.error('上传失败,请重新选择素材进行上传')
reject(error)
}
})
}
}
可以上传文件,但会发现,el-upload自带的进度条不显示了
这里我尝试了很多方法都不行,例如:监听上传进度更新进度时触发up-load的钩子函数等,都不能显示进度条
因此,我只能在插槽中自定义文件列表来显示进度条
<el-upload :auto-upload="false" accept=".mp4,.avi,.mp3,.png,.jpg,.jpeg,.gif,.bmp,.webp,.svg" drag
v-model:file-list="fileList" :on-preview="handlePictureCardPreview" ref="upload" :on-progress="handleProgress">
<template #default>
<div class="el-upload__text">
拖拽文件到这里 或者 <em>点击选择文件</em>
</div>
</template>
//自定义文件列表
<template #file="{file}">
<div class="file-list-item cursor-pointer">
<span>{{ file.name }}</span>
<el-progress class="mt-2" :stroke-width="3" color="#409eff" v-if="file.status === 'uploading'" :percentage="file.percentage" />
</div>
</template>
</el-upload>
<el-button @click='sureUpload'>上传</el-button>
这时候进度条了,但有一个问题是,我的file文件对象中的status没有uploading,未上传的文件和正在上传的文件status都是’ready’,如果没有这种情况的朋友可忽略这里
<el-progress class="mt-2" :stroke-width="3" color="#409eff" v-if="file.status === 'ready'" :percentage="file.percentage" />
//设置为ready就可以显示出来进度条了,但还没有上传时也会显示出来,这里没办法又加上了限制条件
<el-progress class="mt-2" :stroke-width="3" color="#409eff" v-if="file.status === 'ready' && file.percentage !== 0" :percentage="file.percentage" />
//加上限制条件后未上传时不显示进度条了,但也会有问题,如果上传文件较小,监听进度时,进度条直接就为100了,由于进度条100后就不显示,因此页面上看不到有显示进度条的变化,即一直不显示进度条
显示进度条后又有了新的问题
通过插槽实现自定义进度条显示后,覆盖了默认的el-upload文件渲染,因此,文件后的状态以及删除文件的功能没有了,因此自定义文件列表时,除了进度条,还要自定义一下上传状态(例如:成功/失败)和删除文件
最终结果
//结构
<template #file="{file}">
<div class="file-list-item cursor-pointer">
<!-- 点击预览 -->
<span @click="handlePictureCardPreview(file)" class="flex-1">{{ file.name }}</span>
<!-- 显示进度条 -->
<el-progress class="mt-2" :stroke-width="3" color="#409eff" v-if="file.status === 'ready' && file.percentage !== 0" :percentage="file.percentage" />
<!-- 显示文件上传状态 -->
<span v-if="file.status === 'success'" style="color: green;"><el-icon><CircleCheck /></el-icon></span>
<span v-if="file.status === 'fail'" style="color: red;"><el-icon><CircleClose /></el-icon></span>
<!-- 删除文件 -->
<el-button class="w-[50px] h-[32px] border-[0] text-[20px] delete-btn" icon="close" @click="handleRemove(file)" />
</div>
</template>
//js
methods:{
handleRemove(file){
// 删除文件的方法
const index = this.fileList.indexOf(file);
if (index !== -1) {
this.fileList.splice(index, 1); // 从 fileList 中删除文件
}
},
},
handlePictureCardPreview(file) {
let url
if (file.status === 'success') {
url = file.url
} else {
url = URL.createObjectURL(file.raw)
}
//判断url是否图片 png jpg jpeg gif
let reg = /\.(png|jpg|jpeg|gif|svg|ico)$/
if (reg.test(url) || file.raw?.type.includes('image')) {
this.dialogImageUrl = url
this.dialogVisible = true
return
}
window.open(url, '_blank');
},
//css样式
<style scoped lang="scss">
.file-list-item {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
/* 隐藏删除按钮,只有鼠标悬浮时显示 */
.delete-btn {
display: none;
position: absolute;
right: 0;
}
/* 鼠标悬浮时,显示删除按钮 */
.file-list-item:hover .delete-btn {
display: inline-block;
}
</style>