封装进度条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.hqwc.cn/news/234111.html

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

相关文章

共享办公室平台和普通品牌之间存在哪些区别?三个角度告诉你答案

共享办公室平台是一种新兴的办公模式&#xff0c;它与传统的办公品牌有很多不同之处&#xff0c;主要可以从以下几个角度进行分析&#xff1a; 空间使用&#xff1a;共享办公室平台是一种基于共享经济理念的办公方式&#xff0c;它将空间、设施、服务等资源进行整合和优化&…

家电产品扇叶零部件自动化三维检测设备高精度3D测量系统-CASAIM-IS(2ND)

一、背景介绍 某家电制造商希望对其生产的家电产品零部件进行高精度的3D测量&#xff0c;以确保零部件的尺寸精度和质量符合严格的标准&#xff0c;零部件的形状复杂且多样化&#xff0c;对于一些细节部位的测量精度要求极高。本文将介绍CASAIM-IS&#xff08;2ND&#xff09;…

【目标检测】进行实时检测计数时,在摄像头窗口显示实时计数个数

这里我是用我本地训练的基于yolov8环境的竹签计数模型&#xff0c;在打开摄像头窗口增加了实时计数显示的代码&#xff0c;可以直接运行&#xff0c;大家可以根据此代码进行修改&#xff0c;其底层原理时将检测出来的目标的个数显示了出来。 该项目链接&#xff1a;【目标检测…

【JMeter】菜单栏介绍

【菜单栏】 1. Tools 导入curl接口信息 作用&#xff1a;快速导入接口信息&#xff0c;响应头和缓存信息等 Log level临时修改日志等级 作用&#xff1a; 从勾选的level开始往更高等级level抓取log日志等级优先级&#xff1a; ALL < TRACE < DEBUG <INFO<WA…

Flutter应用程序加固的问题及解决方案

​&#x1f680;Flutter应用程序加固的问题及解决方案引言在移动应用开发中&#xff0c;为了保护应用程序的安全性&#xff0c;开发者需要对应用进行加固。在使用Flutter技术进行应用程序开发时&#xff0c;也需要注意应用程序的安全问题和加固方案。本文将介绍在Flutter应用程…

【JavaEE初阶】 详解HTTPS协议加密过程

文章目录 &#x1f334;HTTPS协议是什么&#xff1f;&#x1f384;运营商劫持事件&#x1f38b;HTTPS的工作过程&#x1f6a9;对称加密&#x1f6a9;非对称加密&#x1f6a9;引入证书&#x1f6a9;完整流程 &#x1f333;HTTPS加密总结⭕总结 &#x1f334;HTTPS协议是什么&…

ROS vscode使用基本配置

1、创建ros工作空间 2、启动 vscode 3、vscode 中编译 ros ctrl shift B 调用编译&#xff0c;选择:catkin_make:build 修改.vscode/tasks.json 文件 4、 创建 ROS 功能包 选定 src ---> create catkin package 依次设置包名、添加依赖 5、C 实现 在功能包的 src 下…

Python开发运维:PyMongo 连接操作 MongoDB

目录 一、理论 1.PyMongo模块 2.Mongo Shell 二、实验 1. Windows11安装MongoDB 7.0.4 2.Windows11安装MongoDB Shell 2.1.0 3.PyMongo 连接 MongoDB&#xff08;无密码方式&#xff09; 4.PyMongo 连接 MongoDB&#xff08;有密码方式&#xff09; 5.PyMongo 操作 Mo…

实现校园网开机自启动部署

❤️博客主页&#xff1a; iknow181&#x1f525;系列专栏&#xff1a; Python、JavaSE、JavaWeb、CCNP&#x1f389;欢迎大家点赞&#x1f44d;收藏⭐评论✍ 目录 一.准备工作 1、IDE安装 2、安装Selenium 1.介绍 2.下载 3、安装pywifi 1.介绍 2.下载 4、下载浏览器驱…

C++ Primer学习笔记 第2章 变量和基本类型

2.1 基本内置类型 2.1.2 类型转换 首先了解下取模和取余的区别&#xff01;&#xff01;&#xff01;[取模与取余的区别] 当我们赋给无符号类型一个超出它表示范围的值时&#xff0c;结果是初始值对无符号类型表示数值总数取模后的余数。如8bit大小的unsigned char 可以表示…

Java实现集合和Excel文件相互转换

目录 一、集合转化为Excel文件二、Excel文件转化为集合 一、集合转化为Excel文件 效果如下&#xff0c;是将集合转化为Excel文件&#xff0c;Excel包含合并单元格。 实体类&#xff1a; Data public class ClassGrade {/** 年级 */private String grade;/** 班主任 */privat…

SSM6 11-27 SpringMvc过滤器和异常处理

try catch:处理异常 throw/throws:不处理 抛出 jvm中断程序运行 打印错误信息 web:经典三层模型&#xff1a; dao(mapper) service web层 异常抛给web层Controller类的方法&#xff0c;每个方法可能处理异常,可能处理异常代码相似,造成重复代码重复编写 web层再往上抛 …