因业务需求,需要在表单中使用多个上传组件进行文件上传。且上传文件格式,数量,限制大小均有区别,表单也有多个,为了代码可读性易维护于是把el-upload组件化开发。
1.upload.vue(子组件)
<template>
<div>
<el-upload class="upload-demo" :accept="types" :action=uploadUrl :headers="{'Authorization': tokenValue}"
:before-upload="handleBeforeUpload" :file-list="fileList" :limit="limit" :on-exceed="handleExceed"
:on-success="handleSuccess" :on-remove="delfile" :on-preview="preview" :on-progress="progress">
<el-button size="small" type="primary">点击上传</el-button>
<div slot="tip" class="el-upload__tip" v-if="types.length < 10">只能上传{{types}}文件,且不超过{{msize}}MB</div>
<div slot="tip" class="el-upload__tip" v-if="types.length > 10">只能上传非视频文件,且单个文件大小不大于10MB ,最多10个文件</div>
</el-upload>
</div>
</template>
<script>
import {
getToken
} from '@/utils/auth';
import {
delfileList,
downloadFile
} from "@/api/tool/common.js";
export default {
props: {
// 文件上传个数限制
limit: {
type: Number,
required: true,
default: 1
},
// 文件上传大小限制
msize: {
type: Number,
required: true,
default: 10
},
// 上传文件类型
types: {
type: String,
required: true,
default: '.pdf'
},
// 上传文件对象
uploadObject: {
type: String,
required: true,
default: ''
}
},
data() {
return {
uploadUrl: process.env.VUE_APP_SERVICE_URL + "/common/upload", // 上传的图片服务器地址
tokenValue: 'Bearer ' + getToken(),
fileList: [],
fileLists: [], //传给后端删除的url
}
},
methods: {
// 上传文件大小超出限制提示
handleBeforeUpload(file) {
// 截取上传文件的后缀名
//let fileType = file.name.substring(file.name.lastIndexOf("."));
let fileType = this.matchFileType(file.name)
// 判断文件名的类型,允许多种就判断多个
if (fileType == this.types.substring(this.types.lastIndexOf(".") + 1)) {
} else {
ElMessage.error('文件类型必须为' + this.types + '格式')
// 返回false 就不会执行上传操作了
return false
}
const maxSize = this.msize * 1024 * 1024; // 10MB,根据你的需求设置最大文件大小
if (file.size > maxSize) {
ElMessage({
message: `文件大小超过了${maxSize / (1024 * 1024)}MB的限制`,
type: 'error'
});
return false;
}
},
// 单文件上传后顶替的原文件
progress(event, file, fileList) {
console.log(event.percent)
if (event.percent == 100) {
if (this.limit == 2) {
console.log(1111111)
if (this.fileLists.length > 0) {
delfileList({
fileUrl: fileList[0].response.url
}).then(response => {
fileList.shift();
console.log(2222222)
});
}
} else {
return
}
}
},
// 上传个数超出限制提示
handleExceed() {
this.$message.error('只能上传' + this.limit + '个文件,请删除当前文件后重新上传');
},
// 上传成功时的回调
handleSuccess(response, file, fileList) {
// response 是服务器返回的数据
// file 是上传成功的文件对象
// fileList 是文件列表
// console.log('文件列表', fileList);
this.fileLists = [];
for (const item of fileList) {
this.fileLists.push({
'uploadObject': this.uploadObject,
'name': item.response.originalFilename,
'url': item.response.url,
})
}
this.$emit('child-event', this.fileLists);
console.log(this.fileLists, "1213");
},
// 点击上传后的文件列表进行预览
preview(e) {
downloadFile({
fileUrl: e.response.url,
fileName: e.response.originalFilename
})
// val为传入的pdf下载地址链接
.then((res) => {
let blob = new Blob([res], {
type: "application/pdf"
});
// pdfurl即转化后的结果
let pdfurl = window.URL.createObjectURL(blob);
// 新标签页打开,即可预览并下载
window.open(pdfurl);
});
},
// 移除文件时删除
delfile(e) {
delfileList({
fileUrl: e.response.url
}).then(response => {
if (response.code == 200) {
this.$message.success(response.msg);
} else {
this.$message.error(response.msg);
}
});
},
matchFileType(fileName) {
// 后缀获取
let suffix = '';
// 获取类型结果
let result = '';
if (!fileName) return false;
try {
// 截取文件后缀
suffix = fileName.substr(fileName.lastIndexOf('.') + 1, fileName.length)
// 文件后缀转小写,方便匹配
suffix = suffix.toLowerCase()
} catch (err) {
suffix = '';
}
// fileName无后缀返回 false
if (!suffix) {
result = false;
return result;
}
let fileTypeList = [
// 图片类型
{
'typeName': 'image',
'types': ['png', 'jpg', 'jpeg', 'bmp', 'gif']
},
// 文本类型
{
'typeName': 'txt',
'types': ['txt']
},
// excel类型
{
'typeName': 'excel',
'types': ['xls', 'xlsx']
},
{
'typeName': 'word',
'types': ['doc', 'docx']
},
{
'typeName': 'pdf',
'types': ['pdf']
},
{
'typeName': 'ppt',
'types': ['ppt']
},
// 视频类型
{
'typeName': 'video',
'types': ['mp4', 'm2v', 'mkv']
},
// 音频
{
'typeName': 'radio',
'types': ['mp3', 'wav', 'wmv']
}
]
// let fileTypeList = ['image', 'txt', 'excel', 'word', 'pdf', 'video', 'radio']
for (let i = 0; i < fileTypeList.length; i++) {
const fileTypeItem = fileTypeList[i]
const typeName = fileTypeItem.typeName
const types = fileTypeItem.types
console.log(fileTypeItem);
result = types.some(function(item) {
return item === suffix;
});
if (result) {
return typeName
}
}
return 'other'
}
}
}
</script>
<style>
</style>
2.父组件引用示例
<Upload :limit='2' :msize='60' :types='`.pdf`' :uploadObject='`revenueList`'
@child-event="handleChildEvent" />
tips:这里的limit 如果是只能上传单文件其实传的值是2,其他文件数量例如2 3 4 5都是直接传就可以。因为有一个业务需求是在单文件上传文件后再次上传需要顶替掉原来的文件,所以通过这个值在子组件中进行处理实现。