封装进度条onUploadProgress+axios取消请求的上传组件

目录

定时模拟进度条

方法

A.axios

B.xhr

取消请求 

完整代码

A.自定义上传组件

B.二次封装组件

情况

增加cancelToken不生效,刷新页面

进度条太快->设置浏览器网速


定时模拟进度条

    startUpload() {if (!this.file) return;const totalSize = this.file.size;let uploadedSize = 0;const interval = setInterval(() => {if (uploadedSize >= totalSize) {clearInterval(interval);// this.state_tip = STATE_TIPS.get('上传成功');} else {uploadedSize += 1024;this.progress = Math.round((uploadedSize / totalSize) * 100);}}, 200);}

方法

A.axios

 uploadQuery() {if (!this.file) return;this.state_tip = STATE_TIPS.get('上传中');this.progress = 0;// headers = {'Content-Type': 'multipart/form-data'}const formData = new FormData()formData.append('file', this.file)axios.post(this.uploadPath, formData, {headers: {"X-Requested-With": "XMLHttpRequest",},onUploadProgress: (progressEvent: ProgressEvent) => {console.log("onUploadProgress");if (progressEvent.lengthComputable) {this.progress = Math.round((progressEvent.loaded / progressEvent.total) * 100);console.log(this.progress);}},}).then((res: any) => {if (res && res.code == 200) {this.uploadExel = res.data;this.state_tip = STATE_TIPS.get('上传成功');console.log(this.uploadExel);this.$emit("update:uploadExel", this.uploadExel);} else {this.state_tip = STATE_TIPS.get('其他');this.state_tip.tip = res.msg || '请取消上传,更换符合模板要求的文件';}}).catch((error: any) => {this.state_tip = STATE_TIPS.get('上传失败');}).finally(() => {this.uploaded = true;this.$emit("update:uploaded", this.uploaded);});}

B.xhr

   uploadQuery(file: File) {// headers = {'Content-Type': 'multipart/form-data'}const formData = new FormData()formData.append('file', file)const xhr = new XMLHttpRequest();xhr.open("POST", this.uploadPath, true);xhr.upload.onprogress = (event) => {if (event.lengthComputable) {this.uprogress = Math.round((event.loaded / event.total) * 100);}};xhr.onload = () => {console.log(xhr);if (xhr.status === 200) {const res = JSON.parse(xhr.responseText);console.log(res);console.log(res.code);if (res.code === 200) {this.uploadExel = res.data;this.state_tip = "上传成功";this.uploaded = true;console.log(this.uploadExel);this.$emit("update:uploaded", this.uploaded);this.$emit("update:uploadExel", this.uploadExel);} else {// 处理上传失败情况this.state_tip = "上传失败";}}};xhr.onerror = () => {// 处理上传出错情况this.state_tip = "上传出错";};xhr.send(formData);// request.post(this.uploadPath, formData).then((res: any) => {//     if (res.code == 200) {//         this.uploadExel = res.data;//         this.state_tip = STATE_TIPS.get('上传成功');//         this.uploaded = true;//         this.$emit("update:uploaded", this.uploaded);//         this.$emit("update:uploadExel", this.uploadExel);//     } else {//     }// })}

取消请求​​​​​​​

完整代码

<UploadComp :uploadPath="PATH" :fileLogPath="PATH.replace('uploadExcel?wpReleId=','getOtherIndexFileLog/')" :uploaded.sync="uploaded" :uploadExel.sync="uploadExel" @cancelUpload="cancelUpload" /><!-- <SingleUploadComp :uploadPath="PATH" :uploaded.sync="uploaded" :uploadExel.sync="uploadExel" @cancelUpload="cancelUpload" /> -->

A.自定义上传组件

<template><div class="upload-list-dragger" :uploadPath="uploadPath" :fileLogPath="fileLogPath"><div v-if="!file" @click="openFileInput" @dragenter="onDragEnter" @dragover="onDragOver" @drop="onDrop":class="{ 'drag-over': isDragOver }"><input type="file" ref="fileInput" style="display: none;" @change="onFileChange" :accept="format" /><div class="custom-drag-style"><img src="@/assets/img/upload.png" class="upload-icon" /><div class="upload-click-drag">点击或拖拽上传文件</div><!-- 使用正则表达式替换所有点号 --><div class="upload-tip">请上传{{ format.replace(/\./g, "") }}格式文件,上传多份文件时以最后一次为准</div></div></div><div v-else class="custom-upload-card"><img class="upload-card-icon" src="@/assets/img/excel.png" /><div class="upload-card-state"><div><span class="file-name">{{ file.name }}</span><span class="cancel-upload" @click="cancelUpload"><mds-icon type="line-close" /></span></div><div class="progress-bar" :style="{ width: progress + '%', backgroundColor: state_tip.color }"></div><div class="span-container"><span :style="{ color: state_tip.state === '上传中' ? '#A8ACB3' : state_tip.color }">{{state_tip.tip}}</span><span v-if="state_tip.state === '上传中'">{{ progress + '%' }}</span><span v-if="state_tip.state === '上传失败'" class="span-operate" underline@click="restartUpload">重新上传</span><span v-if="state_tip.state === '上传成功'" class="span-operate" underline@click="downloadQuery">下载结果明细</span></div></div></div></div>
</template><script lang="ts">
import { Component, Vue, Prop } from 'vue-property-decorator';
import request from '@/utils/request'
import axios, { Canceler } from 'axios';
const STATE_TIPS = new Map([['其他', { state: '其他', color: 'orange', tip: '' }], ['上传中', { state: '上传中', color: '#1564FF', tip: '文件上传解析中…' }], ['上传失败', { state: '上传失败', color: '#DD2100', tip: '上传失败,请重新上传' }], ['上传成功', { state: '上传成功', color: '#00AF5B', tip: '上传成功!' }]])
@Component({components: {}
})
export default class UploadComp extends Vue {@Prop({ required: true }) private uploadPath!: string@Prop({ required: true }) private fileLogPath!: string@Prop({ default: '.xls' }) private format!: string //形如".xls,.csv,.xlsx"uploadExel: any = {succList: []}uploaded: boolean = false;file: File | null = null;source = axios.CancelToken.source();progress = 0;isDragOver = false;data() {return {state_tip: {},}}created() {console.log(this.fileLogPath);}onFileChange(event: Event) {const target = event.target as HTMLInputElement;this.fileValidator(target.files);//可能为null}fileValidator(files: FileList | undefined | null) {if (files && files.length > 0) {// 上传多份文件时以最后一次为准const file = files[0];if (this.isValidFormat(file)) {this.file = file;console.log(this.file);this.uploadQuery();} else {alert(`请上传${this.format.replace(/\./g, "")}格式文件。`);}} else {alert(`请上传文件!`);}}uploadQuery() {if (!this.file) return;this.state_tip = STATE_TIPS.get('上传中');this.progress = 0;// headers = {'Content-Type': 'multipart/form-data'}const formData = new FormData()formData.append('file', this.file)// 在合适的地方定义取消令牌和取消函数const CancelToken = axios.CancelToken;// 判断上一次的请求是否还在继续,如果还在继续,则取消上一次的请求if(this.source.token._listeners!=undefined ){this.source.cancel("取消请求")this.source = axios.CancelToken.source()}request.post(this.uploadPath, formData, {onUploadProgress: (progressEvent: ProgressEvent) => {console.log("Upload progress:", progressEvent);this.progress = Math.round((progressEvent.loaded / progressEvent.total) * 100);console.log("进度:", this.progress);},cancelToken:this.source.token,}).then((res: any) => {if (res && res.code == 200) {this.uploadExel = res.data;this.state_tip = STATE_TIPS.get('上传成功');console.log(this.uploadExel);this.$emit("update:uploadExel", this.uploadExel);this.uploaded = true;this.$emit("update:uploaded", this.uploaded);} else {this.state_tip = STATE_TIPS.get('其他');this.state_tip.tip = res.msg || '请取消上传,更换符合模板要求的文件';}}).catch((error: any) => {this.state_tip = STATE_TIPS.get('上传失败');})}downloadQuery() {request.get(this.fileLogPath).then((res: any) => {var aLink = document.createElement("a");aLink.style.display = "none";aLink.href = res.data[0].fileUrldocument.body.appendChild(aLink);aLink.click();document.body.removeChild(aLink);})}cancelUpload() {console.log("取消上传")this.state_tip = STATE_TIPS.get('其他');this.progress = 0;this.file = null;if (this.uploaded) {this.$emit('cancelUpload', this.uploadExel.fileLogId)}else{this.source.cancel("请求已被取消")this.source = axios.CancelToken.source()}}restartUpload() {this.uploadQuery();}openFileInput() {const fileInput = this.$refs.fileInput as HTMLInputElement;fileInput.click();}// 拖动文件进入上传区域onDragEnter(event: DragEvent) {// 防止浏览器默认的拖放行为event.preventDefault();this.isDragOver = true;}// 拖动文件在上传区域中移动onDragOver(event: DragEvent) {//防止浏览器默认的拖放行为event.preventDefault();}// 放置拖动的文件onDrop(event: DragEvent) {event.preventDefault();this.isDragOver = false;this.fileValidator(event.dataTransfer?.files)//可能为undefined}isValidFormat(file: File) {const supportedFormats: string[] = this.format.split(','); // 将 format 字符串拆分成数组const fileExtension = '.' + file.name.split('.').pop(); // 获取文件名的扩展名return supportedFormats.some((supportedFormat: string) => {return fileExtension === supportedFormat;});}
}
</script><style>
.upload-list-dragger {width: 800px;height: 160px;border: 1px dashed rgba(206, 212, 224, 1);border-radius: 4px;display: flex;align-items: center;
}.upload-list-dragger:hover {background-color: #eef8ff;}.custom-drag-style {height: 140px;width: 780px;background-color: #fff;flex-wrap: wrap;display: flex;justify-content: center;align-items: center;flex-direction: column;cursor: pointer;.upload-icon {width: 24px;height: 24px;}.upload-click-drag {width: 144px;height: 24px;font-family: PingFangSC-Regular;font-size: 16px;font-weight: 400;line-height: 24px;color: rgba(69, 71, 77, 1);text-align: left;display: block;}.upload-tip {height: 24px;font-family: PingFangSC-Regular;font-size: 14px;font-weight: 400;line-height: 24px;color: rgba(168, 172, 179, 1);text-align: left;display: block;}
}.custom-upload-card {display: flex;align-items: center;height: 71px;.upload-card-icon {width: 71px;}.upload-card-state {height: 100%;display: flex;flex-direction: column;justify-content: space-around;.file-name {font-family: PingFangSC-Regular;font-size: 16px;font-weight: 400;line-height: 16px;color: rgba(69, 71, 77, 1);text-align: left;margin-right: 12px;}.cancel-upload {cursor: pointer;}.progress-bar {height: 8px;border-radius: 8px;}/* 进度条看作是由两个嵌套的<div>元素构成,外部的.progress-bar元素和内部的<div> */.progress-bar div {width: 638px;height: 8px;background-color: rgba(228, 231, 237, 1);border-radius: 8px;}.span-container {width: 690px;display: flex;justify-content: space-between;align-items: center;font-family: PingFangSC-Regular;font-size: 14px;font-weight: 400;line-height: 24px;.span-operate {color: #1564FF;cursor: pointer;}}}}
</style>

B.二次封装组件

mds-upload内部取消上传,但组件会阻止Lits的改变,并呈现上传失败的样式,再次点击才能返回到上传界面 

<template><mds-upload ref="uploadRef" :path="uploadPath" name="file" :beforeUpload="onBeforeUpload":getUploadParams="getUploadParams" :disabled="false" :multiple="false" :accept="format" :onComplete="onUploadComplete":onError="onUploadError" :onChange="onListChange" listType="imgCard" :limit="1" :dragable="true"><template v-slot:dragStyle><div class="custom-drag-style"><img src="@/assets/img/upload.png" class="upload-icon" /><div class="upload-click-drag">点击或拖拽上传文件</div><!-- 使用正则表达式替换所有点号 --><div class="upload-tip" slot="tip">请上传{{ format.replace(/\./g, "") }}格式文件,上传多份文件时以最后一次为准</div></div></template></mds-upload>
</template>
<script lang="ts">
import { Component, Vue, Prop } from 'vue-property-decorator'
@Component({components: {}
})
export default class SingleUploadComp extends Vue {@Prop({ required: true })  private uploadPath!: boolean@Prop({ default: '.xls' }) private format!: string //形如".xls,.csv,.xlsx"uploadExel: any = {succList: []}uploaded:boolean= falseonBeforeUpload(files: File[], callback: (files: File[]) => void) {callback(files)}getUploadParams(file: File, callback: (data: any) => void) {const formData = new FormData()formData.append('file', file)const cbData = {data: formData,withCredentials: true}callback(cbData)this.$refs.uploadRef.$el.querySelector('.upload-list-dragger').style.display = "none";}/*** @param res 响应结果* @param oriFile 原始文件*/onUploadComplete(res: any, oriFile: File) {const errEle = this.$refs.uploadRef.$el.querySelector('.mds-upload-card-data-error')if (res.data.code == 200) {this.uploadExel = res.data.data;this.$emit("update:uploadExel", this.uploadExel); errEle.innerHTML = "上传成功!";this.uploaded = true;this.$emit("update:uploaded", this.uploaded); } else {errEle.innerHTML = res.data.msg;errEle.style.color = "orange";}}onUploadError(err: any, oriFile: File) {const errEle = this.$refs.uploadRef.$el.querySelector('.mds-upload-card-data-erro')errEle.innerHTML = "上传失败,请重新上传";}onListChange(uploadList: any[]) {console.log('on list change')if (uploadList.length == 0) {if (this.uploaded) {console.log("取消上传")this.$emit('cancelUpload', this.uploadExel.fileLogId)}this.$refs.uploadRef.$el.querySelector('.upload-list-dragger').style.display = "block";}}
}  
</script>
<style lang="scss" scoped>
::v-deep .upload-list-dragger {// position: relative;width: 800px;height: 160px;border: 1px dashed rgba(206, 212, 224, 1);border-radius: 4px;.custom-drag-style:hover {background-color: #eef8ff;}.custom-drag-style {height: 140px;background-color: #fff;flex-wrap: wrap;display: flex;justify-content: center;align-items: center;flex-direction: column;cursor: pointer;.upload-icon {width: 24px;height: 24px;}.upload-click-drag {width: 144px;height: 24px;font-family: PingFangSC-Regular;font-size: 16px;font-weight: 400;line-height: 24px;color: rgba(69, 71, 77, 1);text-align: left;display: block;}.upload-tip {width: 326px;height: 24px;font-family: PingFangSC-Regular;font-size: 14px;font-weight: 400;line-height: 24px;color: rgba(168, 172, 179, 1);text-align: left;display: block;}}
}::v-deep .mds-upload-card {position: relative;width: 800px;height: 160px;border: 1px dashed rgba(206, 212, 224, 1) !important;border-radius: 4px;
}::v-deep .mds-upload-card:hover .mds-upload-card-eyes {display: none;
}::v-deep .mds-upload-card-icon {width: 71px;height: 71px;display: block;&::before {content: '';display: block;width: 71px;height: 71px;background: url('../../../assets/img/excel.png');background-size: 71px 71px;z-index: 9999;}
}::v-deep .mds-upload-card-data-name {width: 114px;height: 24px;font-family: PingFangSC-Regular;font-size: 16px;font-weight: 400;line-height: 24px;color: rgba(69, 71, 77, 1);text-align: left;
}::v-deep .mds-upload-card-data {.mds-upload-card-data-error {color: #00AF5B;height: 24px;font-family: PingFangSC-Regular;font-size: 14px;font-weight: 400;line-height: 24px;text-align: left;}.mds-upload-card-data-size {height: 24px;font-family: PingFangSC-Regular;font-size: 14px;font-weight: 400;line-height: 24px;text-align: left;}
}
</style>

情况

增加cancelToken不生效,刷新页面

进度条太快->设置浏览器网速

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/185681.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

NV040C语音芯片:让自助ATM机使用更加安全快捷

近年来&#xff0c;移动支付方式的兴起、银行加强线上化服务、数字人民币项目推进等因素的影响&#xff0c;人们使用ATM机的频率呈现小幅度的下降趋势。然而&#xff0c;自助ATM机并未从我们的视野中消失&#xff0c;它们仍然在金融领域发挥着重要的作用。未来&#xff0c;ATM机…

Wish防关联是什么?Wish要怎样避免违规封店?

四大跨境电商平台之一wish&#xff0c;做跨境电商的很多人可能都听过wish。随着wish不断完善平台制度&#xff0c;对于多账号运营的卖家要求越来越严厉&#xff0c;wish和亚马逊、eBay等其它跨境电商平台一样&#xff0c;不支持一个卖家开设多个账号多家店铺。 但是对于各位卖家…

【力扣:526】优美的排列

状态压缩动态规划 原理如下&#xff1a; 遍历位图可以得到所有组合序列&#xff0c;将这些序列的每一位看作一个数&#xff0c;取序列中1总量的值作为每轮遍历的位&#xff0c;此时对每个这样的位都能和所有数进行匹配&#xff0c;因为一开始就取的是全排列&#xff0c;并且我们…

[Java] 阿里一面~说一下ArrayList 与 LinkedList 区别

文章目录 是否保证线程安全底层数据结构插入和删除是否受元素位置的影响是否支持快速随机访问内存空间占用&#xff1a; 是否保证线程安全 ArrayList 和 LinkedList 都是不同步的&#xff0c;也就是不保证线程安全&#xff1b; 底层数据结构 ● ArrayList 底层使用的是 Obje…

Transformers实战——文本相似度

文章目录 一、改写文本分类1.导入相关包2.加载数据集3.划分数据集4.数据集预处理5.创建模型6.创建评估函数7.创建 TrainingArguments8.创建 Trainer9.模型训练10.模型评估11.模型预测 二、交互/单塔模式1.导入相关包2.加载数据集3.划分数据集4.数据集预处理5.创建模型&#xff…

Anaconda超简单安装教程,超简洁!!!(Windows环境下,亲测有效)

写下这篇文章的动机&#xff0c;是今天在装Anaconda的时候&#xff0c;本来想搜点教程按照教程一步一步安装的&#xff0c;但没想到&#xff0c;所谓“保姆级”教程呀&#xff0c;“最详细”之类的&#xff0c;好复杂。然后一些本应该详细说的反而一笔带过了。所以今天我想把我…

个人成长|普通人要想摆脱贫穷,一定要注意这3点

哈喽呀&#xff0c;你好&#xff0c;我是雷工。 身为普通人&#xff0c;没有背景&#xff0c;没有资源&#xff0c;也没有人脉&#xff0c;在什么都没有的情况下如何才能摆脱贫穷&#xff0c;让生活过得更好。 要想自我蜕变&#xff0c;摆脱贫穷&#xff0c;就必须注意以下3点。…

【人工智能Ⅰ】实验6:回归预测实验

实验6 回归预测实验 一、实验目的 1&#xff1a;了解机器学习中数据集的常用划分方法以及划分比例&#xff0c;并学习数据集划分后训练集、验证集及测试集的作用。 2&#xff1a;了解降维方法和回归模型的应用。 二、实验要求 数据集&#xff08;LUCAS.SOIL_corr-实验6数据…

​[Oracle]编写程序,键盘输入n,计算1+前n项之和。测试案例:输入:10 输出:22.47​

编写程序&#xff0c;键盘输入n,计算1前n项之和。 测试案例&#xff1a; 输入&#xff1a;10 输出&#xff1a;22.47 代码如下&#xff1a; set serveroutput on declare v_sum number:0;v_n number;beginv_n:&n;for i in 1..v_n loopv_sum:v_sumsqrt(i); end loop; d…

21条良心建议!申请香港优才计划注意事项须知!

21条良心建议&#xff01;申请香港优才计划注意事项须知&#xff01; 给即将申请香港优才计划的你21条良心建议&#xff0c;香港优才计划大致流程&#xff1a;先补充好信息差→申请→递交→等待档案号&#xff01; 一、不是获批后孩子就能低分考985/211 这就是大部分中介画的教…

springmvc实验(三)——请求映射

【知识要点】 方法映射概念 所谓的方法映射就是将前端发送的请求地址和后端提供的服务方法进行关联。在springMVC框架中主要使用Controller和RequestMapping两个注解符&#xff0c;实现请求和方法精准匹配。注解符Controller Spring中包含了一个Controller接口&#xff0c;但是…

虚拟机安装centos7系统后网络配置

一.桥接网络和nat网络的区别1&#xff0c;桥接模式&#xff08;如果外部访问虚拟机&#xff0c;最好选这个&#xff09; 通过使用物理机网卡 具有单独ip,但是需要手动配置。 在bridged模式下&#xff0c;VMWare虚拟出来的操作系统就像是局域网中的一台独立的主机&#xff0c;它…

跨境在线客服系统:打破国界的沟通壁垒

跨境在线客服系统在如今全球化的时代中扮演着重要的角色。随着电子商务的兴起&#xff0c;越来越多的企业将目光投向了国际市场。然而&#xff0c;跨境交流带来了语言、文化、时区等各种难题&#xff0c;给客服工作带来了巨大的挑战&#xff0c;而跨境在线客服系统成为了解决这…

力扣题:字符的统计-11.30

力扣题-11.30 [力扣刷题攻略] Re&#xff1a;从零开始的力扣刷题生活 力扣题1&#xff1a;49. 字母异位词分组 解题思想&#xff1a;将单词进行排序之后通过哈希表进行返回 class Solution(object):def groupAnagrams(self, strs):""":type strs: List[str]:…

Node.js+Express+Nodemon+Socket.IO构建Web实时通信

陈拓 2023/11/23-2023/11/27 1. 简介 Websocket WebSocket是一种在单个TCP连接上提供全双工通讯的协议。特别适合需要持续数据交换的服务&#xff0c;例如在线游戏、实时交易系统等。 Websocket与Ajax之间的区别 Ajax代表异步JavaScript和XML。它被用作一组Web开发技术&…

如何在Docker环境下安装Firefox浏览器并结合内网穿透工具实现公网访问

文章目录 1. 部署Firefox2. 本地访问Firefox3. Linux安装Cpolar4. 配置Firefox公网地址5. 远程访问Firefox6. 固定Firefox公网地址7. 固定地址访问Firefox Firefox是一款免费开源的网页浏览器&#xff0c;由Mozilla基金会开发和维护。它是第一个成功挑战微软Internet Explorer浏…

从薛定谔的猫——量子理论基础

在介绍量子理论基础之前&#xff0c;先介绍一下薛定谔的猫的故事&#xff0c;这个故事可能大多数朋友并不陌生&#xff0c;下面首先回顾一下&#xff1a; 薛定谔的猫是一个在量子力学中用来说明量子叠加态和测量结果的思维实验。这个思维实验最早由物理学家Erwin Schrdinger在1…

深眸科技|AI+机器视觉加速进入工业制造,成为提升智能制造必选项

随着人工智能技术的飞速发展&#xff0c;AI视觉与机器视觉技术正在加速进入工业制造中。机器视觉技术赋予机器新活力与新智慧&#xff0c;不仅让机器实现精密工作的完成&#xff0c;还让其能够代替部分脑力活动&#xff0c;具有更高的智慧与能力。 深眸科技CEO周礼表示&#x…

基数排序及利用数组简化解题

红豆不堪看&#xff0c;满眼相思泪 本文主要是帮助大家熟练掌握利用数组进行有关判断的题目&#xff0c;看完本文后在之后的刷题中都可以利用这种思想&#xff0c;当然举例中的题目利用该种方法可能不是最优解&#xff0c;但绝对是你看到题目不用思考太多就可以做出来的方法&am…

容器有挂载目录的时候,容器反向生成为镜像,挂载的内容不会保留。只有实打实拷贝进容器的反向生成镜像才会保留。

无容器目录挂载 1、也就是说宿主机未与容器进行路径映射&#xff0c;故我们可以直接使用指令: docker commit 容器名称/容器ID 像名:标签号&#xff0c;把容器保存为镜像; (其中镜像名和标签号是我们随机取的&#xff0c;新镜像名以及我们的标签号!) 2、我们在不能判断容器与宿…