IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 关于利用Axios的onUploadProgress记录文件上传进度和CancelToken取消文件传输项目记录 -> 正文阅读

[JavaScript知识库]关于利用Axios的onUploadProgress记录文件上传进度和CancelToken取消文件传输项目记录

一、 项目简述
我们做的是一套聊天软件, 目前的文件传输是无法取消发送的, 用户很有可能发了不该发的文件给别人, 却又无法取消, 只能默默等待上传结束的一瞬间选择撤回消息, 那需求就来了.
(来自产品经理)“ 聊天模块中传输文件显示传输进度条,需要支持取消, 并且能够点击重新发送该文件”

二、项目结构
我们的聊天数据是采用better-sqlite3建立本地数据库,实现的消息存储,建立多张表(比如chat, message,user等), 发送文件是先生成一个local文件id, 通过axios post文件片段到文件服务器进行传输.

因此该需求要实现的变更显而易见:

  1. 想办法获取axios的上传进度, 并且记录下数据, 便于vue开发的组件可以获取该进度, 进行渲染.
  2. 由于存在传送多个文件的post请求, 因此需要在每个文件对应的post请求过程pending状态中, 能够取消对应文件的上传.

三、 确定方案
针对(二)中描述的问题, 通过查阅Axios官网API, 很快就敲定了解决策略

  1. 利用axios的请求配置中的 -> onUploadProgress 处理原生进度事件.
    (详情可以参考Axios官网 https://axios-http.com/zh/docs/req_config)

  2. 取消文件的方式根据文档(https://axios-http.com/zh/docs/cancellation),有两种方案, 一是采用以 fetch API 方式取消请求(AbortController), 二是通过Axios的 cancel token. 其实更推荐用第一种方案, 不过要求是axios版本最低为0.22.0, 由于我们的项目即将重构, 老版本就还是暂用以前的0.19版本, 因此选择了CancelToken方案.

四、 实战部分
介绍完需求和方案确立过程, 开始尝试在项目中使用.
(1) 文件传输进度条显示部分
1.针对数据库的操作
在ChatFile表中增加extra_param字段,存储上传过程中的进度数据.
在Message表中关联对应msg_id对应Chat, 通过chat_id关联chatFile的进度, 存储在file_upload_progress中, 在实际聊天中用于显示, 具体细节不做描述, 涉及业务架构.与本文无关.

2.在Axios请求配置中增加onUploadProgress用于记录当前的上传进度数据:

...
await uploadFile (param, {
	onUploadProgress: (progress) => {
	    const uploadProgress = ((progress.loaded / progress.total) * 100) | 0;
	    chatFile.extra_param = String(uploadProgress);
	  	ChatFileTable.updateChatFileById(db, localFileId, chatFile);
	  	updateStoreWithChatIdMsgId(store, chatFile.chat_id, chatFile.msg_id);
	    }, // 这一步将该文件存入Message表中, 在组件中已经是可读取状态
	},
}).then(...
...
  1. 在组件中读取进度,用于显示:(业务代码已省略)
<template>
...
 <div v-if="uploadProgress" class="upload-progress">
    {{ displayUploadProgress }}
  <el-progress
    v-if="progressPercentage"  
    :percentage="progressPercentage"
    :show-text="false"
    color="#FC8A3D"
    />
</div>
...
</template>
<script lang="ts">
get uploadProgress() {
    return this.message.file_upload_progress || 0;
}

get displayUploadProgress() {
   return `正在上传 ${this.uploadProgress}%`;
 }

get progressPercentage() {
   return Number(this.uploadProgress);
}
</script>

效果图:
在这里插入图片描述

(2) 取消传输

  1. 核心思想—— 采用vuex存储对应file_id以及它的post请求的cancelToken, 在组件中点击取消时, 调用CancelToken.source的API进行source.cancel()实现取消.
// 当执行一个axios的post请求时, 存入该文件的file_id和对应的cancelToken,维护一个全局变量
[MUTATIONS.CHAT_CORE_UPDATE_FILE_CANCEL_TOKEN](
state: IState,
{ file_id, cancelToken }: { file_id: string; cancelToken: CancelTokenSource }
) {
    state.fileCancelTokenList.push({ file_id, cancelToken });
},
// 执行完取消操作后, 删除缓存中的cancelToken, 避免冗余
[MUTATIONS.CHAT_CORE_FILE_CANCEL_TOKEN_UNSET](
state: IState, file_id: string) {
  if (file_id) {
    state.fileCancelTokenList = state.fileCancelTokenList.filter((file) => file.file_id !== file_id);
   }
},
  1. 增加Axios配置cancelToken.source
const updateFileCancelToken = (store: any, file_id: string, cancelToken: CancelTokenSource) => {
  if (store) {
    store.commit(MUTATIONS.CHAT_CORE_UPDATE_FILE_CANCEL_TOKEN, { file_id, cancelToken });
  }
};

...
const CancelToken = axios.CancelToken;
const source = CancelToken.source(); // 创建CancelToken实例
updateFileCancelToken(store, localFileId, source);
    serverFileId = await uploadChatFile(uploadParams, { 
        onUploadProgress: (progress) => {
       ...
    },
    cancelToken: source.token, // 为该post请求配置对应的cancelToken
    }).then((f) => {
    Logger.info(`uploadChatFile finished: ${f.id} `);
    return f.id;
  });
    ...
  1. 组件中执行取消传输
<template>
<i class="cancel-btn el-icon-circle-close"
  @click.stop="cancelTransfer"
 ></i>
</template>
<script>
cancelTransfer() {
  if (this.fileCancelTokenList) {
    const fileCancelToken = this.fileCancelTokenList.find((file) => file.file_id === this.fileId);
    const cancelToken = fileCancelToken.cancelToken;
    if (cancelToken) {
      cancelToken.cancel();
      this.$store.commit(MUTATIONS.CHAT_CORE_FILE_CANCEL_TOKEN_UNSET, this.fileId);
    } else {
      console.log(`本地未找到fileId:${this.fileId},对应的 axios CancelToken`, this.fileCancelTokenList);
    }
  }
}
</script>

综上就实现了一整套文件上传进度条显示, 以及取消传输的功能了, 重传仅需再次执行该axios的post请求即可.

做的过程中非常希望能在国内论坛看见一套完整的业务实现方案, 但是结果是千篇一律的复制粘贴, 最后还是结合官网和stackoverflow并且加上自己的尝试做出来, 希望用这篇文章记录自己实现该功能的同时, 也能帮助到更多有相同业务的程序员们.
如果有更好的实现方法, 欢迎评论区各位大佬探讨

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-04-24 09:20:29  更:2022-04-24 09:21:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 1:31:04-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码