前端大文件分片上传

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
					}
				}
			}
		}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

证书(公钥):网络安全的关键

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

【算法刷题】链表笔试题解析(1)

一、链表分割 题目描述&#xff1a; 链接&#xff1a;链表分割 题目分析&#xff1a; 这题直接处理并不好做&#xff0c;我们可以构建前后两个链表&#xff0c;将小于x值的结点放在链表a内&#xff0c;将其它结点放在链表b内&#xff0c;这样将原链表遍历完后&#xff0c;原链…

OSCP靶场--image

OSCP靶场–image 考点(CVE-2023-34152 suid strace提权) 1.nmap扫描 ## ┌──(root㉿kali)-[~/Desktop] └─# nmap -Pn -sC -sV 192.168.178.178 --min-rate 2500 Starting Nmap 7.92 ( https://nmap.org ) at 2024-03-27 23:43 EDT Nmap scan report for 192.168.178.17…

手机照片恢复:两种方法轻松找回您的珍贵照片!

我们的日常生活中&#xff0c;苹果手机已经成为了记录珍贵时刻的得力工具&#xff0c;而其中最重要的要数照片了。然而&#xff0c;有时候不可避免地会出现误删照片的情况&#xff0c;可能是因为手误、设备故障或其他原因。 当您发现重要的照片不见了&#xff0c;往往会感到焦…

「18」如何让你直播间增加高级质感,效果滤镜是你不二选择?

「18」效果滤镜给你的布景增加质感&#xff0c;更具视觉效果 首先&#xff0c;安装&#xff08;模糊滤镜的‘streamfx’&#xff09;安装包。安装成功后&#xff0c;StreamFX 会出现在 OBS 的菜单栏上。在OBS软件里滤镜可分为效果滤镜和音视频滤镜。 一、音视频滤镜 在选择「…

yolov8 pose keypoint解读

yolov8进行关键点检测的代码如下&#xff1a; from ultralytics import YOLO# Load a model model YOLO(yolov8n.pt) # pretrained YOLOv8n model# Run batched inference on a list of images results model([im1.jpg, im2.jpg]) # return a list of Results objects# Pr…

阿里云效CICD流水线提交前后端项目

后端 一、新建流水线 1进入流水线 2新建流水线 3选择流水线模板 二、上传后端项目 1 将后端项目发布至代码仓库后&#xff0c;在流水线中选择流水线源 我们在选择流水线源之后会出现扫描失败的情况 查看日志发现是因为我们的项目是多模块项目&#xff0c;再扫描的时候无法在…

浏览器扩展程序增加 vue_dev_tools 调试工具

1、引言 在做 Vue 项目的开发时&#xff0c;我们经常需要在页面上调试&#xff0c;接下来介绍如何在浏览器扩展程序增加 vue_dev_tools 调试工具。 Download the Vue Devtools extension for a better development experience 翻译&#xff1a;下载Vue Devtools扩展以获得更好…

C语言例4-30:将一个正整数的各位数字逆序输出

算法分析&#xff1a; 提取某一个正整数的最末一位数字&#xff0c;采用取模10的余数获得&#xff0c;以此类推即可。 代码如下&#xff1a; //将一个正整数的各位数字逆序输出 #include<stdio.h> int main(void) {int i,r;printf("输入一个正整数&#xff1a; \…

地方废物回收机构管理的设计与实现|Springboot+ Mysql+Java+ B/S结构(可运行源码+数据库+设计文档)

本项目包含可运行源码数据库LW&#xff0c;文末可获取本项目的所有资料。 推荐阅读100套最新项目持续更新中..... 2024年计算机毕业论文&#xff08;设计&#xff09;学生选题参考合集推荐收藏&#xff08;包含Springboot、jsp、ssmvue等技术项目合集&#xff09; 目录 1. …

雷尼绍 VIONiC高精度光栅尺品助力高精度运动控制系统

随着科技的不断进步&#xff0c;对运动控制精度的要求不断提高。雷尼绍Renishaw推出的VIONiC系列是一款超高精度、超小型的一体化数字增量式光栅&#xff0c;可提供直接的数字位置反馈&#xff0c;具有卓越的测量性能、极高的运行速度和可靠性&#xff0c;成为高精度运动控制系…

C语言-Win11安装古老的VC6.0

win11安装VC6 有些学校一直还在使用VC6.0&#xff0c;我们尝试在Win1 下安装这个老古董&#xff0c;以下是在win11下安装VC6.0的方法。 点击安装文件 输入产品序列号 修改公共安装文件夹 如果C盘空间足够可以不用修改。 此处会发现鼠标一直在转圈不能完成更新系统&#xff0c;可…

领导驾驶舱下钻404问题解决

领导驾驶舱下钻404问题解决 问题 领导驾驶舱点击下钻页面 报404, 涉及到学工系统和sso认证系统 思路 传参 https://xxx:9007/getLoginUrl 转发到 https://xxx/getLoginUrl 修改nginx配置 location /getLoginUrl {proxy_pass http://127.0.0.1:80;}报了500错误 清理缓存后…

9.windows ubuntu 子系统,centrifuge:微生物物种分类。

上次我们用了karken2和bracken进行了物种分类&#xff0c;这次我们使用centrifuge. Centrifuge 是一种用于快速和准确进行微生物分类和物种鉴定的软件。其主要功能包括&#xff1a; 快速分类和物种鉴定: Centrifuge 可以对高通量测序数据&#xff08;如 metagenomic 或 RNA-Se…

JAVA------基础篇

java基础 1.JDK JDK :java development kit JRE&#xff1a;java runtime environment JDK包含JRE java跨平台&#xff1a;因为java程序运行依赖虚拟机&#xff0c;虚拟机需要有对应操作系统的版本&#xff0c;而jre中有虚拟机。 当你想要在Linux系统下运行&#xff0c;则需要…

JavaScript 权威指南第七版(GPT 重译)(四)

第九章&#xff1a;类 JavaScript 对象在第六章中有所涉及。该章将每个对象视为一组独特的属性&#xff0c;与其他对象不同。然而&#xff0c;通常有必要定义一种共享某些属性的对象类。类的成员或实例具有自己的属性来保存或定义它们的状态&#xff0c;但它们还具有定义其行为…

vue3+vite - 报错 import.meta.glob() can only accept string literals.(详细解决方案)

报错说明 在vue3+vite项目中,解决报错: [plugin:vite:import-analysis] import.meta.glob() can only accept string literals. 如果我们报错差不多,就可以完美搞定这个错误。 解决教程 这个错误,是因为

3GPP 协议资料学习和文档下载

一、登录3GPP官网 3GPP – The Mobile Broadband Standard 二、选择Specifications Per TSG Round 三、选择ftp下载路径 四、选择不同阶段的3GPP协议 包含了从1999年到R18,甚至更新到当前最新的协议。 五、查看对应版本的LTE或者5G NR协议 其中LTE射频相关章节为36.521系列&…

进销存记账软件有哪些?中小商户的进销存记账管理软件选购指南

进销存记账软件已经成为众多实体店不可或缺的管理工具。利用这类软件&#xff0c;实体店能够解决手工记账效率低下、对账繁琐且容易出错等问题。 然而&#xff0c;许多实体店都是小本经营&#xff0c;对于进销存记账软件的选择缺乏经验&#xff0c;导致随意选购的结果往往令人…

C++开发基础理解std::string 对象的生命周期,避免悬空指针或内存访问错误

一、字符串的两种类型互换 在C开发中&#xff0c;const char * 和 std::string 是用于表示字符串的两种不同类型。它们之间可以相互转换。但是需要注意const char * 和 std::string 的互换场景错误。 const char * 到 std::string 的转换&#xff1a; 可以使用 std::string 的…