视频上传 - 断点续传那点事

在上一篇文章中,我们讲解了分片上传的实现方式。在讲解断点续传之前,我要把上篇文章中留下的问题讲解一下。读过上一篇文章的小伙伴们都知道,对于分片上传来说,它的传输方式分为2种,一种是按顺序传输,一种是并发的方式传输

上一篇里,我们只讲解了第一种方式,第二种方式并没有过多的去讲解。接下来,小编会带着大家,一步步拆解这个内容。大家系好安全带,面试题要来了。

如何实现分片的并发上传?

大家肯定都刷到过这样的面试题:给你100张图片,如何实现并发上传
首先我们要知道,浏览器一次性能发送多少个请求?答案是6个。那也就是说,我们需要设计一个流程,每次并发6个,直到所有的请求都完成响应。
那如何实现并发呢?

Promise似乎提供了一些方法,比如 Promise.allSettledPromise.allPromise.race

那这个时候,面试题又来了,它三的区别是什么在这个场景里,使用哪个API更合理?

共同点:参数都是由Promise实例组成的数组。

不同点:返回值不同。Promise.allSettled返回的是所有实例的状态数组。all与race返回的都是对象,最先成功或者失败的对象。

在我们这个场景里,我们优先选择 Promise.allSettled。知道了并发的方式还远远不够,假设我们有10个地址,一次并发发送6个请求,所以需要2次并发6个请求。那这个2次该如何得知呢?最简单也最实用的方案就是通过 Array.splice方法 来切割数组。因为splice进行删除操作时会影响到原数组,也就是原数组里也没有了被删除的元素。那我们就可以通过while循环来判断原数组是否还有剩余元素。没有剩余元素意味着并发请求结束了。

这个时候一个知识点也过来了。一起复习一下,slice与splice有什么区别?

  • 作用不一样。slice只能用来删除元素。splice可通过参数来决定删除或者添加元素的操作。
  • 对原数组的影响不一样。slice不会影响原数组。无论splice进行的是删除操作 还是 添加操作,它都会影响到原数组。

讲了这么多理论,也是时候动手实践一波了:

let arr = [{name: 1},{name: 2},{name: 3},{name: 4},{name: 5},{name: 6},{name: 7},{name: 8},{name: 9},{name: 10},{name: 11},
];async function ax(){while(arr.length > 0){let newArr = arr.splice(0, 6);let result = await Promise.allSettled(newArr.map(item => {return new Promise((resolve, reject) => {setTimeout(() => {return resolve(item.name)},1000)})}));console.log('result是撒谎:', result);}
}ax();

执行一下上述代码,我们会发现,按照了我们的预期,过了1s,控制台同时打印了1-6。再过了1s,控制台同时的打印了剩余元素。

那我们把这个思想转换到 分片上传的代码里。

// Video组件里的其他内容均不变,有不清晰的请看前2篇文章 ==========// 并发分片上传
concurrencyUploadChunkFile = async () => {let self = this;// 定义每块体积大小为5MBlet chunk_size = 5 * 1024 * 1024;// 当前上传的文件对象let fileObj = this.state.fileObj;// 当前上传的文件对象的体积let allSize = this.state.fileObj.size;// 当前文件被切割的总分片数量let allChunkCount = Math.ceil(allSize / chunk_size);// chunk文件集合let chunkArr = [];for (let index = 0; index < allChunkCount; index++){let startIndex = index * chunk_size;let endIndex = Math.min(startIndex + chunk_size, allSize);chunkArr.push({data: fileObj.slice(index * chunk_size,endIndex),filename: `chunk-${index}`,chunkIndex: index});}// 开始并发分片上传while(chunkArr.length > 0){let reqArr = chunkArr.splice(0, 6);let reqArrFactory = reqArr.map(item => {return new Promise((resolve, reject) => {let result = this.uploadChunkReq(item.data, item.chunkIndex, 'chunk');return resolve(result);})})let resArr = await Promise.allSettled(reqArrFactory);console.log('6个请求的响应如何:', resArr);}// 合并请求// this.mergeChunk();render(){return <div><button onClick={this.concurrencyUploadChunkFile}>并发上传</button></div>}}

在上述代码中,我们定义了分片的体积为5M,此时假如我们分片上传了一个61M的视频,根据计算,会得到13个分片,如果我们控制网速,能明显的看到分层才对。因为毕竟发了3波,每波都是发送6个请求,每波之间都是按顺序的。就像下面这样:

在这里插入图片描述
并发上传分片到这里就结束啦。但如果想扩展的话,其实还有很多考题,就拿并发来举例子,大家可能还会听到一些考题,比如实现并发的方法有哪些?Promise.allSetlled是如何实现的等等。

我想说的是,大家不要去刻意背这些东西,因为这些题的本质就一个,就是js异步对象的运行机制。当你深入理解了就会发现,真的是举一反三。

断点续传

直到目前为止,大家有没有发现,我们进展的过于顺利,如果在上传分片的过程中出现了失误,我们应该怎么办?

断点续传是一个防错机制。它在大文件上传失败时,不必重新来过,从断掉的地方重新上传即可。

如何实现呢?很简单,从哪个分片断掉,就从哪块上传呗。

但是大家也会发现,即使是最简单的场景,根据每个项目实现分片上传的方式不同,断点续传的方法也不尽一样。因为断点续传的方式不一样,所以导致后端实现合并分片的方式也会随之改变。举个例子:

假如,我们有13个分片,序号分为是1-13,先并发1-6,此时我们发现分片6失败了,然后我们维护一个失败分片的数组,将分片6 push进去。接着并发 7 -12,此时都成功了。最后发送13,也成功了。因为分片6失败了,所以我们还需要再发送分片6,最后发现分片6也成功了。但是对于后端来说,在合并分片的时候就需要新增排序逻辑了,因为分片的序号对不上了。大家懂我的意思吧。

这里我们来新增前端处理断点续传的逻辑。逻辑如下:

  • 定义一个失败的分片集合
  • while循环时,通过判断原分片数组的长度是否为0,来确定所有的分片是否都上传了。
  • 在上传的过程中,如果有分片失败的,就将它push到 失败分片集合里。
  • 当原分片集合为空时,意味着此时应该重传失败的分片了。

// 其他内容不变 =======// 并发上传分片
concurrencyUploadChunkFile = async () => {let self = this;// 定义每块体积大小为5MBlet chunk_size = 5 * 1024 * 1024;// 当前上传的文件对象let fileObj = this.state.fileObj;// 当前上传的文件对象的体积let allSize = this.state.fileObj.size;let allChunkCount = Math.ceil(allSize / chunk_size);// 失败的分片集合(新增++++++++++++++++++++++++++++)let failedChunkArr = [];// chunk文件集合let chunkArr = [];for (let index = 0; index < allChunkCount; index++){let startIndex = index * chunk_size;let endIndex = Math.min(startIndex + chunk_size, allSize);chunkArr.push({data: fileObj.slice(index * chunk_size,endIndex),filename: `chunk-${index}`,chunkIndex: index});}// 开始分片上传(update++++++++++++++++++++++++++++++++++++++++)while(chunkArr.length > 0 || failedChunkArr.length > 0){let reqArr = chunkArr.length > 0 ? chunkArr.splice(0, 6) : failedChunkArr.splice(0, 6);let reqArrFactory = reqArr.map(item => {return new Promise((resolve, reject) => {let result = this.uploadChunkReq(item.data, item.chunkIndex, 'chunk');if (result?.code != 200){failedChunkArr.push(item);}return resolve(result);})})let resArr = await Promise.allSettled(reqArrFactory);console.log('6个请求的响应如何:', resArr);}// 合并请求// this.mergeChunk();}

最后

好啦,本篇文章到这里就结束啦,如果上述过程中有明显的错误,欢迎大家指正,希望我讲的对大家有帮助,那么我们下期再见啦,拜拜~~

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

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

相关文章

GPT-1, GPT-2, GPT-3, GPT-3.5, GPT-4论文内容解读

目录 1 ChatGPT概述1.1 what is chatGPT1.2 How does ChatGPT work1.3 The applications of ChatGPT1.3 The limitations of ChatGPT 2 算法原理2.1 GPT-12.1.1 Unsupervised pre-training2.1.2 Supervised fine-tuning2.1.3 语料2.1.4 分析 2.2 GPT-22.3 GPT-32.4 InstructGPT…

【操作系统】MacOS虚拟内存统计指标

目录 命令及其结果 参数解读 有趣的实验 在 macOS 系统中&#xff0c;虚拟内存统计指标提供了对系统内存使用情况和虚拟内存操作的重要洞察。通过分析这些指标&#xff0c;我们可以更好地了解系统的性能状况和内存管理情况。 命令及其结果 >>> vm_stat Mach Virtu…

常见云计算服务模式( IaaS基础架构即服务、PaaS平台即服务、SaaS软件即服务)

常见云计算服务模式 &#xff08; IaaS基础架构即服务、PaaS平台即服务、SaaS软件即服务&#xff09; 零、00时光宝盒 世界并不完美&#xff0c;面对很多事情我们都很无奈甚至悲哀&#xff0c;但生活总要继续下去&#xff0c;不止是为了自己。抱怨没有用&#xff0c;顾影自怜也…

51单片机之LED灯模块篇

御风以翔 破浪以飏 &#x1f3a5;个人主页 &#x1f525;个人专栏 目录 点亮一盏LED灯 LED的组成原理 LED的硬件模型 点亮一盏LED灯的程序设计 LED灯闪烁 LED流水灯 独立按键控制LED灯亮灭 独立按键的组成原理 独立按键的硬件模型 独立按键控制LED灯状态 按键的抖动 独立按键…

Python(SQLite)executescript用法

SQLite 数据库模块的游标对象还包含了一个 executescript() 方法&#xff0c;这不是一个标准的 API 方法&#xff0c;这意味着在其他数据库 API 模块中可能没有这个方法。但是这个方法却很实用&#xff0c;它可以执行一段 SQL 脚本。 例如&#xff0c;如下程序使用 executescr…

Android中的MVVM

演变 开发常用的框架包括MVC、MVP和本文的MVVM&#xff0c;三种框架都是为了分离ui界面和处理逻辑而出现的框架模式。mvp、mvvm都由mvc演化而来&#xff0c;他们不属于某种语言的框架&#xff0c;当存在ui页面和逻辑代码时&#xff0c;我们就可以使用这三种模式。 model和vie…

uniapp android和微信小程序实现PDF在线预览

在使用uniapp开发移动端时&#xff0c;微信开发者工具里webview能正常打开后端接口返回的pdf文件流。正式发布后&#xff0c;在配置了业务域名和服务器域名的前提下&#xff0c;预览pdf文件却只能看到白屏&#xff0c;因此我猜测微信小程序不能通过webview读取文件流。这个想法…

机器学习的整个流程

机器学习的整个流程定义了数据科学团队执行以创建和交付机器学习模型的工作流。此外&#xff0c;机器学习流程还定义了团队如何协作合作&#xff0c;以创建最有用的预测模型。 机器学习high level的流程 机器学习流程的关键步骤包括问题探索&#xff08;Problem Exploration&a…

Django模板(三)

一、标签URL 返回与给定视图和可选参数相匹配的绝对路径引用(不含域名的 URL) {% url some-url-name v1 v2 %} 第一个参数是url模式名称,后面跟着的是参数,以空格分隔可以使用关键字: {% url some-url-name arg1=v1 arg2=v2 %}如果您想检索命名空间的URL,请指定完全限定…

探讨CSDN等级制度:博客等级、原力等级、创作者等级

个人名片&#xff1a; &#x1f981;作者简介&#xff1a;学生 &#x1f42f;个人主页&#xff1a;妄北y &#x1f427;个人QQ&#xff1a;2061314755 &#x1f43b;个人邮箱&#xff1a;2061314755qq.com &#x1f989;个人WeChat&#xff1a;Vir2021GKBS &#x1f43c;本文由…

Ansible command命令模块 这个模块可以直接在远程主机上执行命令,并将结果返回本主机。

目录 参数介绍练习环境配置主机清单配置无密码链接ping模块 command 命令模块也可以用来安装点东西看个路径 command 指定目录来 指定命令 参数介绍 chdir    # 在执行命令之前&#xff0c;先切换到该目录 executable # 切换shell来执行命令&#xff0c;需要使用命令的绝对…

机器学习数学基础

机器学习基础 1、标量、向量、矩阵、张量2、概率函数、概率分布、概率密度、分布函数3、向量的线性相关性4、最大似然估计5、正态分布(高斯分布)6、向量的外积(叉积)7、向量的内积(点积)8、超平面(Hyperplane)9、广义线性模型(GLM)10、伯努利分布与二项分布11、凸函数…

Java基于微信小程序的驾校报名小程序,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

SERVLET过滤器

SERVLET过滤器 全球因特网用户使用不同类型的Web浏览器访问应用服务器上存储的Web应用程序。每个浏览器根据对应的Web浏览器窗口中的设置显示应用程序中的信息。Web应用程序可能会有一些客户机的Web浏览器不支持的HTML标记或功能。这种情况下,应用程序在客户机的Web浏览器中可…

notepad++成功安装后默认显示英文怎么设置中文界面?

前几天使用电脑华为管家清理电脑后&#xff0c;发现一直使用的notepad软件变回了英文界面&#xff0c;跟刚成功安装的时候一样&#xff0c;那么应该怎么设置为中文界面呢&#xff1f;具体操作如下&#xff1a; 1、打开notepad软件&#xff0c;点击菜单栏“Settings – Prefere…

探索C语言中的联合体与枚举:数据多面手的完美组合!

​ ✨✨ 欢迎大家来到贝蒂大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;C语言学习 贝蒂的主页&#xff1a;Betty‘s blog 1. 联合体的定义 联合体又叫共用体&#xff0c;它是一种特殊的数据类型&…

vue项目打包部署到flask等后端服务里面,实现前后端不分离部署,解决空白页面和刷新页面not fount问题

1. 编译模式一定要设置为esnext&#xff0c;否则会报错&#xff1a; Strict MIME type checking is enforced for module scripts per HTML spec.Expected a JavaScript module script but the server responded with a MIME type of "text/plain". 具体解释可以看vi…

机器学习中常用的性能度量—— ROC 和 AUC

什么是泛化能力&#xff1f; 通常我们用泛化能力来评判一个模型的好坏&#xff0c;通俗的说&#xff0c;泛化能力是指一个机器学期算法对新样本&#xff08;即模型没有见过的样本&#xff09;的举一反三的能力&#xff0c;也就是学以致用的能力。 举个例子&#xff0c;高三的…

删除和清空Hive外部表数据

外部表和内部表区别 未被external修饰的是内部表&#xff08;managed table&#xff09;&#xff0c;被external修饰的为外部表&#xff08;external table&#xff09;&#xff1b; 区别&#xff1a; 内部表数据由Hive自身管理&#xff0c;外部表数据由HDFS管理&#xff1b; …

Rebuild企业管理系统 SSRF漏洞(CVE-2024-1021)

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…