js实现文件切片上传,断点续传

断点续传:顾名思义,继续上次断开的点,继续上传。

思路整理:

拿到文件,对文件进行fingerprint = md5(file),得到文件指纹。
将指纹保存服务器。
切割文件,分段上传,每次上传一段。
服务器根据指纹进行索引判断文件上传进度,直到文件的全部片段上传完毕。
以下文字没有完整的代码,只有基础理论,伸手党绕道。

  1. 读取文件
// 这里只演示单文件上传过程。
var input = document.querySelector('input');
input.addEventListener('change', function() {
    var file = this.files[0];
    //这里是有一个坑的,部分设备(华为部分机型)无法获取文件名称,和文件类型,这个在最后给出解决方案
    var fileType = file.type;
    // getFileType(file, fileType => {})
});
  1. 获取文件指纹
var fingerprint = md5(file);
  1. 文件切割
var reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.addEventListener("load", function(e) {
    //每10M切割一段,这里只做一个切割演示,实际切割需要根据file.size进行循环切割.
    let size = 1024 * 1024 * 10;
    var slice = e.target.result.slice(0, size);
});
  1. h5上传一个(一片)文件
// 一般情况下不需要getFileType。
getFileType(file, fileType => {
    var formdata = new FormData();
    formdata.append('fingerprint', fingerprint);
    // 指纹作为文件名,并拼接文件类型(也可以在服务器断进行文件类型处理)
    formdata.append('filename', fingerprint + '.' + fileType);
    // 做好切片索引,把索引作为切片名称
    // 第一片为了保存指纹,可以尽量切小一点。
    formdata.append('0', slice);
    var xhr = new XMLHttpRequest();
    xhr.addEventListener('load', function () {
        //xhr.responseText
    });
    xhr.open('POST', '');
    xhr.send(formdata);
    xhr.addEventListener('progress', updateProgress);
    xhr.upload.addEventListener('progress', updateProgress);
});

function updateProgress(event) {
    if (event.lengthComputable) {
        //进度条
    }
}

无法获取文件类型的设备解决方案
首先在:http://www.garykessler.net/li…查找对应文件的头信息
这里只给出了常见的图片和视频的文件类型判断

function getFileType(file, back) {
    var name = file.name;
    var type = '';
    if (name) {
        var lastIndex = name.lastIndex('.')
        type = name.substring(lastIndex + 1)
        back(type);
        return;
    }
    // 如果系统无法获取文件类型,则读取二进制流,对二进制进行解析文件类型
    var imgType = {
        'ff d8 ff': 'jpg',
        '89 50 4e': 'png',

        '0 0 0 14 66 74 79 70 69 73 6F 6D': 'mp4',
        '0 0 0 18 66 74 79 70 33 67 70 35': 'mp4',
        '0 0 0 0 66 74 79 70 33 67 70 35': 'mp4',
        '0 0 0 0 66 74 79 70 4D 53 4E 56': 'mp4',
        '0 0 0 0 66 74 79 70 69 73 6F 6D': 'mp4',

        '0 0 0 18 66 74 79 70 6D 70 34 32': 'm4v',
        '0 0 0 0 66 74 79 70 6D 70 34 32': 'm4v',

        '0 0 0 14 66 74 79 70 71 74 20 20': 'mov',
        '0 0 0 0 66 74 79 70 71 74 20 20': 'mov',
        '0 0 0 0 6D 6F 6F 76': 'mov',

        '4F 67 67 53 0 02': 'ogg',
        '1A 45 DF A3': 'ogg',

        '52 49 46 46 x x x x 41 56 49 20': 'avi',
    }
    // 用最长的作为截取边界
    var size = Object.keys(imgType).map(i => i.split(/\s+/).length).sort()[0]
    var reader = new FileReader();
    reader.readAsArrayBuffer(file);
    reader.addEventListener("load", function (e) {
        var result = e.target.result
        if (!result || result.length < size) {
            back('')
            return;
        }
        var slice = result.slice(0, size);
        var view = new Uint8Array(slice);
        var arr = view.map(v => v.toString(16))

        type = imgType[arr.join(' ')];
        if (!type) {
            // 处理一个特殊情况:忽略第4-8位
            arr = arr.map(function (v) {
                if (i > 3 && i < 8) {
                    return 'x';
                }
                return v;
            });
            type = imgType[arr.join(' ')];
        }

        back(type);
    });
}

总结:有了切割上传,有了文件唯一标识信息(文件md5)断点续传只不过是后台的一个小小的判断逻辑而已。

未来,前端,大有可为
有些小伙伴不是太清楚后台的小小的判断是怎么做的:
这里贴一张图给大家参考,自己手画,有点丑,将就下。
在这里插入图片描述

参考文章:http://blog.ncmem.com/wordpress/2023/10/19/js%e5%ae%9e%e7%8e%b0%e6%96%87%e4%bb%b6%e5%88%87%e7%89%87%e4%b8%8a%e4%bc%a0%ef%bc%8c%e6%96%ad%e7%82%b9%e7%bb%ad%e4%bc%a0/
欢迎入群一起讨论

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值