首页 > 其他分享 >前端大文件分片上传

前端大文件分片上传

时间:2024-04-16 17:01:09浏览次数:23  
标签:文件 const chunkInfo 前端 await 分片 上传

1.分片上传整体流程
开始上传:前端启动文件分片上传。后端返回唯一标识。
分片上传:获取到上传的文件,然后设置一个固定的分片大小,将文件切成多个小片,计算出每一个分片的MD5值(32位)。将每个分片的内容和MD5标识符一同上传至服务器。服务端接收每个分片及相关信息后,通过对每个分片进行校验,来确保分片的完整性。
结束上传:当分片上传完毕或者前端取消上传时,调用结束上传接口结束此次文件上传操作。结束上传时,服务端判断是正常结束或取消上传来决定后续操作。

 

2.前端具体流程
开始上传,发送开始上传请求,向服务器传递文件名、文件总大小、分片总数和切片大小,获取并保存文件上传的唯一标识符。同时在发送请求前,对上传的文件名进行校验,如果文件名超过最大长度256,则禁止发送请求并向用户提示修改文件名称。
分片上传,首先将文件进行切片,调用切片方法时,需要将文件传递给该方法,然后根据文件的大小来决定每个分片的大小并切分成多个片段,同时计算出总切片数,并为每个切片添加从0开始的顺序索引。随后对每个切片计算出他们的MD5值。最后把这些分片的MD5值和顺序索引保存在浏览器内存中。然后发送上传数据请求,向服务器发送唯一标识符、分片的顺序索引、分片数据,MD5值和当前分片的大小。在每个分片发送请求后,如果发送成功,则将其对应的信息从浏览器内存中删除,并计算出此时的上传进度,然后发送下一个片段直至最后。如果全部上传成功,清空浏览器内存。如果请求发生错误,则对该分片再次发送一次上传请求,如果仍然错误,不再上传,调用结束请求并提示错误原因。
结束上传,如果文件分片全部成功上传,向服务器发送结束请求,传递正常结束状态码,清空浏览器内存。如果主动取消上传则传递取消请求状态码,同时清空浏览器内存,不再继续上传。
3.部分代码

//文件切片,utils
 
import SparkMD5 from 'spark-md5'
 
export async function getChunkList (files) {
    const file = files
    console.log(file);
    const fileSize = file.size // 文件大小
    const fileName = file.name
 
    let chunkSize = 0;
    if (fileSize <= 5 * 1024 * 1024) { // 0-5M,不分片
        chunkSize = fileSize;
    } else if (fileSize <= 20 * 1024 * 1024) { // 5-20M,每个分片大小1M
        chunkSize = 1024 * 1024;
    } else if (fileSize <= 50 * 1024 * 1024) { // 20-50M,每个分片大小2M
        chunkSize = 2 * 1024 * 1024;
    } else if (fileSize <= 100 * 1024 * 1024) { // 50-100M,每个分片大小4M
        chunkSize = 4 * 1024 * 1024;
    } else if (fileSize <= 200 * 1024 * 1024) { // 100-200M,每个分片大小6M
        chunkSize = 6 * 1024 * 1024;
    } else if (fileSize <= 500 * 1024 * 1024) { // 200-500M,每个分片大小10M
        chunkSize = 10 * 1024 * 1024;
    } else if (fileSize <= 1024 * 1024 * 1024) { // 500M-1G,每个分片大小20M
        chunkSize = 20 * 1024 * 1024;
    } else { // 1G以上,每个分片大小20M
        chunkSize = 20 * 1024 * 1024;
    }
    const totalChunks = Math.ceil(fileSize / chunkSize)
    let start = 0
    let end = Math.min(chunkSize, fileSize)
    let index = 0 // 分片索引,从0开始
    const chunks = [] // 存储当前文件的分片信息的数组
 
    while (start < fileSize) {
        const chunk = file.slice(start, end)
        const reader = new FileReader()
        const promise = new Promise((resolve, reject) => {
            reader.onload = (e) => { //读取文件分片信息,使用SparkMD5库计算分片的MD5值
                const spark = new SparkMD5.ArrayBuffer()
                spark.append(e.target.result)
                resolve(spark.end())
            }
            reader.onerror = (err) => {
                reject(err)
            }
        })
        reader.readAsArrayBuffer(chunk)
        try {
            const md5 = await promise
            const chunkInfo = { chunk, md5, index }
            chunks.push(chunkInfo)
        } catch (err) {
            reject(err)
        }
        //更新循环起止位置
        start = end
        end = Math.min(start + chunkSize, fileSize)
        index++
    }
    // 将当前文件的分片信息数组存入总的数组中
    return [chunks, totalChunks, fileSize, fileName, chunkSize] // 返回存储所有文件的分片信息的数组
}     
async handleUpload () {
            this.progressState = 'upload'
            this.wrongNum = 0
            if (this.fileList.length == 0) { //判断是否添加文件
                this.$notify.warning({
                    title: this.$global.warningMessage.title,
                    message: this.$global.warningMessage.fileMessage,
                });
                return
            }
            if (this.file.name.length > 256) {
                this.$notify.warning({
                    title: this.$global.warningMessage.title,
                    message: this.$global.warningMessage.fileNameMessage,
                });
                return
            }
            this.totalSize = this.file.size
            // 调用getChunkList方法获取分片及相关信息
            const [chunks, totalChunks, fileSize, fileName, chunkSize] = await getChunkList(this.file.raw)
            this.totalChunks = totalChunks
            this.fileSize = fileSize
            this.fileName = fileName
            this.chunkList = chunks
            this.chunkSize = chunkSize
            console.log(this.chunkList);
            // 开始上传请求
            await this.startUpload()
            // 遍历分片信息数组,取出除文件分片外的其他信息
            const sessionChunkList = this.chunkList.map(({ chunk, ...rest }) => rest);
            // 将分片其他信息存入sessionStorage中
            sessionStorage.setItem("chunkData", JSON.stringify(sessionChunkList));
            let i = 0;
            while (i < this.chunkList.length && this.wrongNum < 1) { //对分片数组进行遍历
                const chunkInfo = this.chunkList[i];
                const res = await this.uploadChunk(chunkInfo); //调用上传分片方法
                if (res.data.state == 200) {
                    const removeInfo = {
                        md5: chunkInfo.md5,
                        index: chunkInfo.index
                    }
                    await this.handleSuccess(removeInfo, chunkInfo) //调用当前分片上传成功处理函数
                    i++;
                } else {   //上传未成功,重新上传一次
                    const res = await this.uploadChunk(chunkInfo);
                    this.wrongNum += 1
                    if (res.data.state == 200) {
                        this.wrongNum = 0
                        await this.handleSuccess(removeInfo, chunkInfo)
                        i++;
                    } else {  // 重新上传一次后仍未成功
                        const state = this.$global.completeUploadState.cancelUpload
                        await this.completeUpload(state)
                        this.$notify.error({
                            title: this.$global.failedMessage.title,
                            message: res.data.message
                        });
                        this.handleClear()
                        return
                    }
                }
            }
        }

 

标签:文件,const,chunkInfo,前端,await,分片,上传
From: https://www.cnblogs.com/houxianzhou/p/18138626

相关文章

  • 前端学哪些技能饭碗越铁收入还高
    随着经济的下行以及移动互联网发展趋于成熟,对软件开发人员的需求大大减少,互联网行业所有的公司都在降本增效,合并通道,降薪裁员的新闻层出不穷。但相比其他行业,互联网行业的从业者薪资还是比较可观的,但要求也比之前高了很多,需要大家掌握更多的技能和在某些技术领域深耕。本文,我们......
  • redis自学(35)搭建分片集群
    分片集群结构主从和哨兵可以解决高可用、高并发读的问题。但是依然有两个问题没有解决:l 海量数据存储问题l 高并发写的问题使用分片集群可以解决上述问题,分片集群特征:l 集群中有多个master,每个master保存不同数据,因此能存多少取决于master节点的数量,解决了海量数据存储的......
  • React前端技术深度解析与实践
    React作为当今最热门的前端技术之一,以其组件化、高效性和灵活性等特点赢得了广大开发者的青睐。本文将深入探讨React前端技术的核心原理、实践技巧以及未来的发展趋势,帮助读者更好地理解和应用React。一、React的核心原理React的核心原理是组件化开发。组件是React应用的基本构......
  • 微前端--通俗易懂
    是什么微前端是指存在于浏览器中的微服务。微前端是一种类似于微服务的架构,它将微服务的理念应用于浏览器端,即将Web应用由单一的单体应用转变为多个小型前端应用聚合为一的应用。各个前端应用还可以独立运行、独立开发、独立部署。微前端不是单纯的前端框架或者工具,而是一套架......
  • 前端开发框架的选择-Vue.js
    Vue.js秉持简约哲学,通过精炼的代码实现功能——它专注于为Web应用开发提供核心工具,而非让冗余特性成为负担。这种简约设计思路使得代码更加明晰,易于阅读和维护。长远看来,Vue.js的简约特性使得项目运作更为流畅。无论是小型网站还是大型单页应用,Vue.js都能轻松应对——它并非万金......
  • JWT 前端笔记
    JWTJTW全称JsonWebToken没有JWT的时候,服务端给客户端发送信息,客户端返回信息,通常存在cookie或localstorage,不过服务器无法信任这个信息传给服务器的信息可能是被篡改的,也可能是被伪造的JWT的雏形原始信息和密钥一样的情况下才能生成相同签名info.签名返回后,服务器用相......
  • 前端面试题 — webpack
    1.webpack的安装和使用方式安装Node.js和npm首先,确保你的计算机上安装了Node.js和npm(Node包管理器),因为Webpack是通过npm进行安装和管理的。创建项目目录并初始化npmnpminit-y安装Webpacknpminstallwebpackwebpack-cli......
  • 若依解决VUE前端时间显示问题
    参考:https://blog.csdn.net/qq_43544074/article/details/119139313#:~:text=%E6%97%A0%E6%B3%95%E6%AD%A3%E7%A1%AE%E7%9A%84%E6%98%BE%E7%A4%BA%E6%97%B6%E9%97%B4%E3%80%82%20%E8%A7%A3%E5%86%B3%E5%A6%82%E4%B8%8B%EF%BC%9A%201%E3%80%81%E5%9C%A8%E5%90%8E%E7%AB%AF%E4%BB......
  • 纯前端实现发版版本变化后页面重新加载
    0.原理通过在前端静态文件目录下维护一个版本,首次进入页面存储当前版本,轮询查询静态文件版本是否发生变化,如果变化则重新加载页面,如果未变化,则继续轮询1.优点比通过后端维护在数据库版本进行查询消耗更小,不需要查询数据库,也不用走到后台代码层,只需要访问到ngxin/......
  • gitee基于webhooks实现前端简单自动化部署
    1.为什么采用自动化部署简而言之,程序员优秀传统:懒=>高级生产力.基于gitee进行的自动化部署,服务器环境为Ubuntu基于webhooks进行的自动化部署更加轻快便捷2.部署步骤1).服务器购买可以购买阿里云抢占式服务器进行实验,花费应该在一大洋以内,或者直接购买一年低配服务......