大文件分片上传-前端部分

108 阅读1分钟

我们在进行大文件上传时,如果遇到网络或者其他问题,中途中断了上传,用户体验会非常差,这时候我们就应该使用分片上传

前端实现原理及重点代码如下,直接看代码:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- spark-md5在工程化项目中也可通过npm安装 -->
    <script src="./spark-md5.js"></script>
</head>

<body>
    <input type="file" />

    <script>
        const inp = document.querySelector('input');
        
        // 监听上传事件
        inp.onchange = async (e) => {
            const file = e.target.files[0];
            if (!file) {
                return;
            }
            // 将文件以10M一个分片,得到一个都是blob对象的数组
            const chunks = createChunks(file, 10 * 1024 * 1024);
            // 获取一个文件hash,相当于这个文件的身份证号码
            const result = await hash(chunks);
            console.log(result)
            console.log(chunks)
            // 得到文件hash和分片数组后自行上传到后端...
        }

        // 根据分片计算文件hash
        function hash(chunks) {
            return new Promise((resolve) => {
                const spark = new SparkMD5();// 使用SparkMD5得到一个16位的hash值
                function _read(i) {
                    if (i >= chunks.length) {// 递归结束条件
                        resolve(spark.end());// spark.end()结束增量运算,返回一个结果
                        return;// 读取完成
                    }
                    const blob = chunks[i];
                    const reader = new FileReader();// 创建文件读取器
                    reader.onload = (e) => {
                        const bytes = e.target.result;// 读取到的字节数组
                        spark.append(bytes);// 增量运算
                        _read(i + 1);// 递归调用
                    }
                    reader.readAsArrayBuffer(blob);// 将blob类型读取为字节
                }
                _read(0);
            });
        }

        // 分片
        function createChunks(file, chunkSize) {
            const result = [];
            for (let i = 0; i < file.size; i += chunkSize) {
                result.push(file.slice(i, i + chunkSize));
            }
            return result;
        }
    </script>
</body>

</html>