背景 :
项目里的 附件上传 题型组件,用户在上传过程中,如果文件较大,上传过程较慢,而又没有一个类似 Loading... 的加载过程的话,会显得干愣愣的,用户体验较差,所以需要添加一个进度条来提示用户上传的进度,下面有两种方式,一种假的,一种真的,伙伴们可根据需求自行选取实现。
本文章向大家介绍使用 Upload + Progress 实现文件上传进度条实时更新功能,主要包括使用 Upload + Progress 实现文件上传进度条实时更新功能使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
Upload 上传
通过点击或者拖拽上传文件
Progress 进度条
用于展示操作进度,告知用户当前状态和预期。
“ 简单 && 假 ” 的 进度条 :
利用 setInterval 定时器 模拟实现
<template>
<div>
<el-upload
ref="uploadRef"
action="#"
:file-list="fileList"
:on-change="onChangeData"
:http-request="handleRequest"
:before-upload="beforeUpload"
>
<el-button v-show="isShowButton" class="btn upload-btn"
>上传附件</el-button
>
<div slot="tip" class="el-upload__tip">上传文件大小不超过50M</div>
</el-upload>
<el-progress
v-show="showProgress"
:stroke-width="6"
:percentage="progressPercent"
></el-progress>
</div>
</template>
<script>
import { uploadFileApi } from '@/api';
export default {
name: 'uploadFile',
data() {
return {
fileType: '', // 文件类型
fileList: [], // 上传的文件列表
progressPercent: 0, // 进度条百分比
isShowButton: false, // 是否显示上传按钮
showProgress: false, // 是否展示进度条
isAllowFileTypes: false, // 是否为支持的上传类型
allowFileTypes: [], // 存储不支持的文件类型
};
},
methods: {
// 上传的执行方法
onChangeData(file, fileList) {
// 前四行代码为了解决:on-change方法第二次调用不起来的问题
let uploadFilesArr = this.$refs.uploadRef.uploadFiles;
if (uploadFilesArr.length !== 0) {
this.$refs.uploadRef.uploadFiles = [];
}
let arr = file.name.split('.');
this.fileType = '.' + arr[arr.length - 1].toLowerCase();
this.isAllowFileTypes = this.allowFileTypes.includes(this.fileType);
if (this.isAllowFileTypes) {
this.isShowButton = false;
this.fileList = [file];
if (file.status === 'ready') {
this.progressPercent = 0;
this.showProgress = true; // 展示进度条
const interval = setInterval(() => {
if (this.progressPercent >= 99) {
clearInterval();
return;
}
this.progressPercent += 1;
}, 50);
}
if (file.status === 'success') {
this.progressPercent = 100;
this.showProgress = false; // 隐藏进度条
}
}
},
// 文件上传
async handleRequest(data) {
let formdata = new FormData();
formdata.append('file', data.file);
let res = await uploadFileApi(formdata);
let { code } = res;
if (code === '0') {
// 上传成功
// ...
} else if (code === '1') {
// 上传失败
this.isShowButton = true;
this.fileList = [];
}
},
// 上传文件之前的钩子,对文件大小进行校验
beforeUpload(file) {
const isLt2M = file.size / 1024 / 1024 < 50;
if (!isLt2M) {
this.$message.error('上传文件大小大小不能超过 50MB!');
return isLt2M;
}
},
},
};
</script>
真实加载的进度条 :
1、使用 Upload + Progress 实现文件上传进度条实时更新功能,需要借助 http-request 属性。
具体使用方法如下:
// 上传的执行方法
onChangeData (file, fileList) {
// 数据小于0.1M的时候按KB显示
const size = file.size/1024/1024 > 0.1 ? `(${(file.size/1024/1024).toFixed(1)}M)` : `(${(file.size/1024).toFixed(1)}KB)`
file.name.indexOf('M')>-1 || file.name.indexOf('KB')>-1 ? file.name : file.name += size
},
// 文件上传
handleRequest (data) {
let formdata = new FormData()
formdata.append('file', data.file)
const config = {
onUploadProgress: progressEvent => {
// progressEvent.loaded:已上传文件大小
// progressEvent.total:被上传文件的总大小
this.progressPercent = Number((progressEvent.loaded / progressEvent.total * 100).toFixed(2))
}
}
this.$axios.post(this.actionURL,formdata,config).then(res => {
if (res.data.code===1) {}
})
},
2、真实进度条,根据文件上传过程中 文件 切片 实现的
<template>
<div class="uploadBtn">
<el-upload
ref="uploadRefs"
class="upload-demo"
action=""
accept="mp4"
:limit="1"
:file-list="fileListA"
:http-request="UploadFileA"
:on-change="handleChange"
:on-success="handleSuccess"
>
<el-button size="small" type="primary">点击上传</el-button>
</el-upload>
<el-progress v-if="uploading" :percentage="uploadPercentage"></el-progress>
</div>
</template>
<script>
export default {
name: 'Upload',
data() {
return {
fileListA: [], // 上传的文件列表
uploading: false, // 是否正在上传
uploadPercentage: 0, // 进度条百分比
};
},
methods: {
//上传图片到阿里云
UploadFileA(file) {
console.time('executionTime'); //测试文件上传所耗时间开始
const baseUrl = 'https://你的阿里云地址aliyunUrl.com';
const fileName = file.file.uid + file.file.name; //文件信息
const url = baseUrl + '/resource/你的阿里云文件夹地址/' + fileName; //拼接地址
const xhr = new XMLHttpRequest();
xhr.upload.addEventListener('progress', (event) => {
if (event.lengthComputable) {
const percentage = Math.round((event.loaded * 100) / event.total);
this.uploadPercentage = percentage; // 给进度条赋值
}
});
xhr.onreadystatechange = () => {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200 || xhr.status === 201) {
console.log('阿里云文件', xhr);
this.formData.fileUrl = xhr.responseURL;
this.uploadPercentage = 100; // 上传完成后显示100%进度
console.timeEnd('executionTime'); //测试文件上传所耗时间结束,打印时间为所耗时间,为毫秒级
} else {
console.error('上传失败');
}
this.uploading = false; // 设置上传状态为 false,隐藏进度条
}
};
this.uploading = true; // 设置上传状态为 true,显示进度条
this.uploadPercentage = 0; // 设置进度条初始值为0%
xhr.open('PUT', url, true);
xhr.send(file.file);
},
},
};
</script>
相关参数解答:
xhr.onreadystatechange 是 XMLHttpRequest 对象的一个事件处理程序,
它在请求状态发生变化时触发。XMLHttpRequest 对象用于与服务器进行异步通信,onreadystatechange 事件在接收到服务器响应并且请求状态发生变化时被触发。
具体来说,xhr.onreadystatechange 事件在以下几种情况下被触发:
xhr.readyState 的值发生变化时
xhr.status 的值发生变化时
xhr.statusText 的值发生变化时
xhr.response 的值发生变化时
xhr.readyState 是 XMLHttpRequest 对象的属性,表示请求的状态。它有如下几个可能的值:
0:未初始化。XMLHttpRequest 对象已创建或已被 abort() 方法重置。
1:打开。open() 方法已被调用,但 send() 方法未被调用。
2:发送。send() 方法已被调用,并且头部和状态已经可获得。
3:接收。正在接收服务器的响应数据。
4:完成。已经接收到全部响应数据,并且可以在客户端使用了。
在 xhr.onreadystatechange 事件处理程序中,我们通常使用条件判断来确定请求的状态是否满足特定条件,以执行相应的操作。例如,在上面的代码中,我们检查 xhr.readyState 是否等于 XMLHttpRequest.DONE,来确定请求是否已完成。
如果是,则进一步检查 xhr.status 是否为 200 或 201,来确定请求是否成功。
通过使用 xhr.onreadystatechange 事件处理程序,我们可以根据不同的请求状态来执行相应的逻辑,例如更新页面内容、处理错误等。xhr.upload 是 XMLHttpRequest 对象的一个属性,而不是事件处理程序。
xhr.upload 属性是用于处理上传过程中的事件的。它是一个包含了与上传相关事件的 XMLHttpRequestUpload 对象。
在前面提到的代码中,我们使用了 xhr.upload.addEventListener 方法来注册一个 progress 事件监听器。这个事件监听器用于追踪上传的进度。