1、使用elementui上传文件自定义进度条
- 满足上传文件
- 上传文件前显示文字,过程中显示进度条,上传完后显示文字
- 上传过程中可以取消上传
- 上传限制大小,格式,上传文件个数
思路:
- 点击上传后,显示进度条,禁止点击;点击取消,可以点击;上传完成,进度条消失,可以点击;
- 上传完成后,需要接口返回处理内容,上传完成设置为90%,接口返回后设置为100%
- 上传到90%就不能再取消
uploadFile.vue
<template>
<div class="update-file-container">
<!-- 上传 -->
<div class="upload-content">
<el-upload
class="upload-demo"
ref="upload"
:disabled="percentage > 0"
drag
action=""
:limit="1"
accept=".xlsx"
:file-list="fileList"
:show-file-list="false"
:on-exceed="handleExceed"
:before-upload="beforeUpload"
:http-request="uploadFile"
>
<i class="el-icon-upload"></i>
<div v-if="!isShowProgress" class="el-upload-text">
<div class="click-upload-text">点击或将文件拖拽到这里上传</div>
<div class="file-text">文件大小不应超过100M,支持扩展名:.xlsx</div>
</div>
<div v-if="isShowProgress" class="el-upload-progress">
<!-- 进度条上方文件名 -->
<div class="upload-filename">
<div>{{ filename }}</div>
<div :class="percentage >= 90 ? 'noneimg' : 'blockimg'">
<i class="el-icon-circle-close" @click="handleRemove"></i>
</div>
</div>
<!-- 进度条 -->
<el-progress
style="width: 400px"
:percentage="percentage"
:format="format"
:text-inside="true"
:color="customColor"
:stroke-width="4"
>
</el-progress>
<!-- 进度条数字 -->
<div class="percentage-text">已上传{{ percentage }}%…</div>
</div>
</el-upload>
</div>
</div>
</template>
<script>
// 取消上传
let cancel = null
export default {
name: 'uploadfile',
data() {
return {
templateId: this.$route.params.templateId,
// 是否显示进度条
isShowProgress: false,
// 文件
fileList: [],
// 文件名
filename: '',
// 进度条
percentage: 0,
// 进度条颜色
customColor: '#910E0E',
}
},
methods: {
// 文件超出限制个数时提醒
handleExceed() {
this.$message.warning(`当前限制选择 1 个文件,请删除后继续上传`)
},
// 上传前格式验证
beforeUpload(file) {
const fileName = file.name
const fileType = fileName.split('.').pop()
const fileSize = file.size / 1024 / 1024
if (fileType !== 'xlsx') {
this.$message.warning('您好,文件格式不对,请调整后重新上传')
return false
}
if (fileSize > 100) {
this.$message.warning('您好,文件过大,请调整后重新上传')
return false
}
},
// 上传文件
uploadFile(item) {
this.isShowProgress = true
// 上传需要的传参
let fileList = item.file
let form = new FormData()
form.append('file', fileList)
// 添加参数,比如templateId
form.append('templateId', this.templateId)
// 进度条
const uploadProgress = progressEvent => {
this.filename = item.file.name
this.percentage = Number(
((progressEvent.loaded / progressEvent.total) * 100).toFixed(2)
)
// 当上传成功时设为90%,等接口返回结果设为100%
if (this.percentage >= 90) {
this.percentage = 90
}
}
this.$http.fileUpdate
.uploadFile(form, uploadProgress, function (c) {
// 取消上传时,取消接口上传
cancel = c
})
.then(res => {
if (res && res.code === 0) {
this.percentage = 100
// 接口返回后进行的操作
} else if (res && res.code === 500) {
// 上传失败
this.hiddenProgress()
this.$message.warning('您好,文件上传失败,请重新上传')
}
})
.catch(err => {
console.error(err)
})
},
// 清空数据
hiddenProgress() {
this.fileList = []
this.isShowProgress = false
this.percentage = 0
this.filename = ''
},
// 取消上传
handleRemove() {
setTimeout(() => {
cancel('cancel')
this.$message.warning(`取消上传成功`)
this.$refs.upload.abort()
this.hiddenProgress()
})
},
// 进度条内容为空
format() {
return ''
},
},
// 离开页面时取消当前上传操作
beforeDestroy() {
if (this.percentage > 0) {
cancel('cancel')
this.$refs.upload.abort()
this.hiddenProgress()
}
},
}
</script>
<style scoped lang="scss">
.update-file-container {
background: #ffffff;
padding: 28px 24px;
min-height: 956px;
// 上传
.upload-content {
margin-top: 72px;
display: flex;
justify-content: center;
::v-deep .el-upload-dragger {
width: 560px;
height: 259px;
border-radius: 4px;
border: 2px dashed rgba(0, 0, 0, 0.12);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.el-upload-text {
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
line-height: 20px;
padding-top: 16px;
.click-upload-text {
color: rgba(0, 0, 0, 0.84);
}
.file-text {
color: rgba(0, 0, 0, 0.24);
margin-top: 8px;
}
}
}
.el-upload-progress {
display: flex;
flex-direction: column;
align-items: center;
width: 400px;
font-family: PingFang SC;
font-size: 14px;
padding-top: 16px;
.upload-filename {
display: flex;
justify-content: space-between;
width: 400px;
font-weight: 500;
color: rgba(0, 0, 0, 0.6);
.noneimg {
display: none;
}
.blockimg {
display: block;
}
}
.percentage-text {
display: flex;
justify-content: flex-start;
width: 400px;
font-weight: 400;
color: rgba(0, 0, 0, 0.24);
}
}
}
}
</style>
接口:
// 上传文件
export function uploadFile(data, onUploadProgress, cancelToken) {
return axios({
url: '......',
method: 'post',
data,
onUploadProgress
}, "", "", cancelToken)
}
拦截请求时操作:
import axios from 'axios'
export default (options, headers, responseType, cancel) => {
return new Promise((resolve, reject) => {
const CancelToken = axios.CancelToken;
// 创建 axios对象,并设置拦截器
const $axios = axios.create({
baseURL: config.BASE_API_URL,
headers: headers || config.HEADER,
responseType: responseType || 'json',
// 取消操作
cancelToken: cancel ? new CancelToken(cancel) : new CancelToken(function (c) {})
})
// 请求拦截器
$axios.interceptors.request.use(
config => {
return config
},
request => {
return request
},
error => {
return Promise.reject(error)
}
)
// 响应拦截器
$axios.interceptors.response.use(
response => {
......
},
error => {
//主动中断请求
if (error.message && error.message === 'cancel') {
return
}
......
}
)
// 处理请求
$axios(options).then(response => {
resolve(response)
}).catch(error => {
reject(error)
})
})
}