视频上传-分片上传那点事

本文详细介绍了前端如何通过Blob.slice进行文件分片上传,包括代码示例和按顺序发送分片的方法。同时讨论了后端接收分片并进行合并的过程,以及并发控制和错误处理的要点。

在上一篇文章中,我们讲解了从视频上传到保存在服务端的整个过程,在这个过程中,我们又细分了前端上传视频的几种方式,前端处理视频的几种方式,在前后端通信过程中需要注意的哪些点等等。有不清楚的小伙伴可以看看 上篇文章

紧接上文,我们来讲下文件的分片上传。

我们都知道分片上传是为了提升文件保存的速度。那它是如何实现的呢?下面的流程图会是一个很好的解释:

在这里插入图片描述

接下来,我们一步步的拆解。

前端如何进行分割操作

在上篇文章我们知道,通过 Element.files属性 拿到的是FileList集合。FileList集合由File对象组成。File对象又继承Blob对象。所以File对象可以使用slice方法来完成对文件对象的切割。

slice方法具体明细如下:

含义:Blob.slice() 方法用于创建一个包含源 Blob的指定字节范围内的数据的新 Blob 对象。
返回值:一个新的 Blob 对象,它包含了原始 Blob 对象的某一个段的数据。
参数:3个参数,分别如下:

  • start。第一个会被拷贝进新的 Blob 的字节的起始位置。
  • end。这个下标的对应的字节将会是被拷贝进新的Blob 的最后一个字节。
  • contentType。给新的 Blob 赋予一个新的文档类型。这将会把它的 type 属性设为被传入的值。它的默认值是一个空的字符串。

说了一大堆理论,该是实战了,先说一下思路:

  • 先通过input标签上传文件。
  • 上传文件后,会触发input标签的change事件,在这个事件里,通过event.target.files可以获取到上传的文件对象,并且将它保存在state里。
  • 定义每个文件块的大小,然后使用slice进行分割。

代码如下:

class Video extends React.Component {
   
   
    constructor(props){
   
   
        super(props);
        this.state = {
   
   
            fileObj: {
   
   }
        }
    }
    
    // 分片上传
    uploadChunkFile = async () => {
   
   
        // 定义每块体积大小为20MB
        let chunk_size = 20 * 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
            });
        }
    }
    
    // 上传文件触发
    inputChange = async (event) => {
   
   
        let self = this;
        let uploadFileObj = event.target.files[0] || {
   
   };
        this.setState(state => {
   
   
            return {
   
   
                ...state,
                fileObj: uploadFileObj
            }
        });
        return
    }
    
    render(){
   
   
        return <div>
            <button onClick={
   
   this.testConnect}>测试连接</button>
            <input
                type='file'
                onChange={
   
   (event) => this.inputChange(event)}
            />
            <button onClick={
   
   this.uploadChunkFile}>分片上传</button
        </div>
    }
}

当我们上传一个66M的视频时,我们会发现,总的分片数量是4。符合预期。

发送chunk的几种方式

这块无非就2种,分别如下:

  • 将这些分片按照顺序发送给后端。
  • 将这些分片并发的方式发送给后端。这种方式下,需要考虑浏览器一次只能并发6个请求的情况,并且这种方式也是面试中高频考点(如何控制并发)。

在这个功能点里,我们采用按顺序的方式上传分片,因为这种方式是最直观的,会了这种方式,相信分片上传你就完全会了。

但是在实际的项目中,更多的还是并发的场景(我们下篇文章再讲)。

按照顺序发送

这个就是第一个请求成功后,再去发送第二个请求,以此类推…

它也是面试中的一个常考点:如何按照顺序发送请求?如何实现红绿灯效果?等等。

按顺序发送,2种思路,一种是循环,一种是递归

递归这里不用说,重点讲一下循环。

普通的for循环可以做到吗?

答案是可以的。


                
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值