•  分片上传原理:客户端将选择的文件进行切分,每一个分片都单独发送请求到服务端;
  • 断点续传 & 秒传原理:客户端
    发送请求询问服务端某文件的上传状态
    ,服务端响应该文件已上传分片,客户端再将未上传分片上传即可;
    • 如果没有需要上传的分片就是秒传;
    • 如果有需要上传的分片就是断点续传;
  • 每个文件要有自己唯一的标识,这个标识就是将整个文件进行MD5加密,这是一个Hash算法,将加密后的Hash值作为文件的唯一标识;
    • 使用spark-md5第三方工具库,spark-md5是指一个用于计算MD5哈希值的前端JavaScript库
  • 文件的合并时机:当服务端确认所有分片都发送完成后,此时会发送请求通知服务端对文件进行合并操作;

如下图所示是前端分片上传的整体流程:

  • 第一步:将文件进行分片,并计算其Hash值(文件的唯一标识)
  • 第二步:发送请求,询问服务端文件的上传状态
  • 第三步:根据文件上传状态进行后续上传
    • 文件已经上传过了
      • 结束 --- 秒传功能
    • 文件存在,但分片不完整
      • 将未上传的分片进行上传 --- 断点续传功能
    • 文件不存在
      • 将所有分片上传
  • 第四步:文件分片全部上传后,发送请求通知服务端合并文件分片

案例实现

  • 前端使用 Element Plus UI

  • 实现文件选择 → 计算 Hash → 分片上传 → 进度显示

  • 假设后端提供接口

    1. POST /upload/check → 接收 fileHash,返回已上传分片列表

    2. POST /upload/chunk → 上传单个分片

    3. POST /upload/merge → 所有分片上传完成后通知合并

<template><el-upload:file-list="fileList":before-upload="beforeUpload":show-file-list="false"><el-button type="primary">选择文件上传</el-button></el-upload><el-progressv-if="uploading":percentage="uploadProgress":text-inside="true"></el-progress>
</template><script setup>
import { ref } from 'vue';
import SparkMD5 from 'spark-md5';
import axios from 'axios';const fileList = ref([]);
const uploadProgress = ref(0);
const uploading = ref(false);
const chunkSize = 2 * 1024 * 1024; // 2MB// 计算文件Hash
function calculateFileHash(file) {return new Promise((resolve, reject) => {const spark = new SparkMD5.ArrayBuffer();const fileReader = new FileReader();const chunks = Math.ceil(file.size / chunkSize);let currentChunk = 0;fileReader.onload = e => {spark.append(e.target.result);currentChunk++;if (currentChunk < chunks) {loadNext();} else {resolve(spark.end());}};fileReader.onerror = () => reject('文件读取错误');function loadNext() {const start = currentChunk * chunkSize;const end = Math.min(file.size, start + chunkSize);fileReader.readAsArrayBuffer(file.slice(start, end));}loadNext();});
}// 分片上传
async function uploadFileChunks(file, fileHash) {const chunks = Math.ceil(file.size / chunkSize);// 先询问服务端已上传分片const { data } = await axios.post('/upload/check', { fileHash });const uploadedChunks = data.uploaded || [];let uploadedCount = 0;for (let i = 0; i < chunks; i++) {if (uploadedChunks.includes(i)) {uploadedCount++;uploadProgress.value = Math.floor((uploadedCount / chunks) * 100);continue; // 已上传,跳过}const start = i * chunkSize;const end = Math.min(file.size, start + chunkSize);const chunkData = file.slice(start, end);const formData = new FormData();formData.append('file', chunkData);formData.append('fileHash', fileHash);formData.append('index', i);await axios.post('/upload/chunk', formData, {onUploadProgress: e => {// 分片进度可加权到整体进度const chunkProgress = e.loaded / e.total;uploadProgress.value = Math.floor(((uploadedCount + chunkProgress) / chunks) * 100);},});uploadedCount++;uploadProgress.value = Math.floor((uploadedCount / chunks) * 100);}// 分片上传完成,通知合并await axios.post('/upload/merge', { fileHash, totalChunks: chunks });
}// 选择文件上传
async function beforeUpload(file) {uploading.value = true;uploadProgress.value = 0;fileList.value = [file];// 计算Hashconst fileHash = await calculateFileHash(file);// 分片上传await uploadFileChunks(file, fileHash);uploading.value = false;ElMessage.success('文件上传完成!');return false; // 阻止默认上传
}
</script>

1.文件 Hash 的作用是什么?为什么要计算 Hash?

Hash 用作文件的唯一标识,可以判断文件是否已经上传过(秒传),也可以实现断点续传。

同样,合并分片后可以通过 Hash 校验文件完整性。

2.Hash 是怎么计算的?为什么要用增量计算?

使用 FileReader 将文件分片读取,逐块用 SparkMD5 增量计算 Hash。

对大文件一次性计算 Hash 内存占用大且阻塞界面,增量计算避免一次性加载整个文件。

fileReader.readAsArrayBuffer异步读取分片,触发fileReader.onload回调添加到spark中

3.大文件上传可能出现性能瓶颈,你如何优化?

并发上传多分片,充分利用带宽,提高上传速度。

分片大小调节,避免请求次数过多或分片过大导致单次失败。

Hash 计算优化,例如只读取前 N MB + 文件大小组合做快速 Hash。

4.前端上传大量分片时,浏览器内存会不会撑爆?如何避免?

通过分片逐块读取,每次只在内存中处理当前分片,读取完成后释放内存。

5.单个分片上传失败怎么处理?

前端可设置自动重试次数(如 3 次)。

若多次失败,提示用户网络异常或重试。

6.分片上传完成后如何合并?

按分片索引顺序读取所有分片,顺序写入最终文件,生成完整文件。

合并完成后再次计算文件 Hash 或 MD5,与客户端 Hash 比对,如果一致,说明文件完整。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/95734.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/95734.shtml
英文地址,请注明出处:http://en.pswp.cn/web/95734.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

零知开源——基于STM32F103RBT6的智能风扇控制系统设计与实现

✔零知IDE 是一个真正属于国人自己的开源软件平台&#xff0c;在开发效率上超越了Arduino平台并且更加容易上手&#xff0c;大大降低了开发难度。零知开源在软件方面提供了完整的学习教程和丰富示例代码&#xff0c;让不懂程序的工程师也能非常轻而易举的搭建电路来创作产品&am…

ReACT Agent概述

目录 1. 核心思想&#xff1a;解决传统方法的局限性 2. ReACT 的工作原理&#xff1a;一个循环过程 3. 技术实现的关键要素 4. ReACTAgent 在任务中的具体工作流程 5. 优势与重要性 6. 挑战与局限性 总结 ReACT 是一个非常重要的框架&#xff0c;它代表了构建能够推理&a…

必知!机器人的分类与应用:RPA、人形与工业机器人

每当提及“机器人”这三个字&#xff0c;许多人的第一反应或许仍是科幻电影中那种具备人类外形、可自由行走与对话的仿生装置。然而&#xff0c;一个值得深入探讨的科技现实是&#xff1a;我们对于人形机器人的迷恋&#xff0c;更多源自文化叙事与情感投射&#xff0c;而非真实…

最快的 C 语言 JSON 库 - yyjson

文章目录DOM 模式下的性能比对一、AWS EC2 (AMD EPYC 7R32, gcc 9.3)二、iPhone (Apple A14, clang 12)持续更新中 持续更新中 持续更新中一个用 ANSI C(C89) 编写的高性能 JSON 库 API.md DOM 模式下的性能比对 DOM 模式&#xff0c;即构建完整 JSON 内存结构后访问数据的模…

TP8 模型save更新不成功

一、User文件头部代码class User extends Model {const TITLE_NAME 用户;//名称//不能删除protected $name user_; //表名 protected $connection \app\services\database\model\DbConnModel::CONN_DB_SITE; //数据库的连接二、更新部分我要更新user_1用户表中的用户信息$se…

中囯移动电视盒子(魔百和)B860AV2.1-A2和CM311-5-zg刷机手记

文章目录B860AV2.1-A2电视盒子情况打开隐藏或屏蔽的功能进入Recovery模式打开WiFi&#xff08;如果被隐藏&#xff09;打开运维调试打开ADB调试安装第三方应用、设置第三方桌面等&#xff08;Fiddler抓包替换官方App安装包&#xff09;开启ADB和使用ADB禁止“首次启动设置”刷机…

【系统架构设计(14)】项目管理下:软件质量与配置管理:构建可靠软件的基础保障

文章目录一、核心思想二、软件质量属性&#xff1a;定义"好软件"的标准三、质量保证与控制&#xff1a;实现质量标准的方法四、CMMI模型&#xff1a;组织质量能力的演进路径五、软件配置管理&#xff1a;质量成果的保护机制六、软件工具&#xff1a;质量管理的技术支…

码农的“必修课”:深度解析Rust的所有权系统(与C++内存模型对比)

在软件开发的世界里&#xff0c;内存管理是至关重要的一个环节。它是程序运行的基础&#xff0c;直接关系到程序的性能、稳定性和安全性。一个糟糕的内存管理策略&#xff0c;可能导致内存泄漏、野指针、缓冲区溢出等一系列令人头疼的问题&#xff0c;甚至带来灾难性的安全漏洞…

Java全栈学习笔记30

# MySQL 卸载安装版电脑管家/360/控制面板卸载mysql服务即可删除ProgramData中的MySQL目录解压版winr 输入 services.msc 打开服务管理。查看是否存在MySQL&#xff0c;如果存在则删除注册表 winR regedit 打开注册表计算机\HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Servic…

Transformers 学习入门:前置知识补漏

在学习 Transformers 之前&#xff0c;打好神经网络和自然语言处理的基础至关重要。本文整理了需要掌握的核心前置知识&#xff0c;用通俗的例子帮你快速理解复杂概念&#xff0c;为后续学习铺平道路。​ 一、神经网络基础​ 1. 多层感知机&#xff08;MLP&#xff09;&#xf…

双摄工业相机的主要特点和应用场景

双摄工业相机&#xff08;双目摄像头&#xff09;在工业领域中的应用非常广泛&#xff0c;其核心优势在于通过双镜头模拟人眼立体视觉&#xff0c;能够获取深度信息并实现高精度三维重建。 一、双摄工业相机的核心优势 深度感知与三维重建 双目摄像头通过两个镜头从不同角度拍…

YOLOv11改进:FocalModulation替换SPPF(精度更高的空间金字塔池化)

YOLOv11&#xff1a;FocalModulation替换SPPF&#xff08;精度更高的空间金字塔池化&#xff09; 引言 在目标检测领域&#xff0c;YOLO系列算法以其高效性和准确性广受欢迎。作为YOLO系列的最新成员之一&#xff0c;YOLOv11在多个方面进行了优化和改进。其中&#xff0c;空间金…

LLM与数据工程的融合:衡石Data Agent的语义层与Agent框架设计

在数字经济浪潮中&#xff0c;企业数据智能正经历从"工具辅助"到"智能协同"的范式跃迁。传统BI系统受限于静态报表与预设指标&#xff0c;难以应对动态业务场景的复杂需求。衡石科技发布的HENGSHI SENSE 6.0通过"Data AI Agent"架构创新&#x…

假设一个算术表达式中包含圆括号、方括号和花括号3种类型的括号,编写一个算法来判别,表达式中的括号是否配对,以字符“\0“作为算术表达式的结束符

思想:这道题是栈的应用类型&#xff0c;我们可以建立一个栈来保存(,[,{,通过遍历字符串如果是三个左括号其中一个则入栈&#xff0c;当遇到)]}则出栈配对&#xff0c;如果左右匹配&#xff0c;则遍历下一个元素&#xff0c;如果不匹配直接返回&#xff0c;如果遍历字符串结束&a…

鸿蒙Next的UI国际化与无障碍适老化实践:构建全球包容的数字世界

科技不应让任何人掉队&#xff0c;鸿蒙Next正将这一理念变为现实在全球化日益深入的今天&#xff0c;应用的国际化与无障碍设计不再是"锦上添花"&#xff0c;而是不可或缺的核心竞争力。华为鸿蒙Next系统从设计之初就深入考虑了这些需求&#xff0c;为开发者提供了完…

深度学习——迁移学习

迁移学习作为深度学习领域的一项革命性技术&#xff0c;正在重塑我们构建和部署AI模型的方式。本文将带您深入探索迁移学习的核心原理、详细实施步骤以及实际应用中的关键技巧&#xff0c;帮助您全面掌握这一强大工具。迁移学习的本质与价值迁移学习的核心思想是"站在巨人…

RAG|| LangChain || LlamaIndex || RAGflow

大模型&#xff1a;预训练模型 外挂知识库&#xff1a;知识库->向量数据库 输入-》预处理成向量 提示词-》llm归纳总结 离线&#xff1a;企业原文本存到向量数据库 向量&#xff1a; 同一个向量模型&#xff08;第二代检索&#xff0c;推荐&#xff0c;个人助理&#xff0c;…

mcp_clickhouse代码学习

引言:当ClickHouse遇上MCP 作为一个基于Model Context Protocol(MCP)框架的ClickHouse查询服务器,mcp_clickhouse不仅在技术实现上展现了优雅的设计思路,更在架构层面提供了许多值得借鉴的解决方案。 一、项目概览:架构初探 mcp_clickhouse是一个专为ClickHouse数据库设计…

前端三件套+springboot后端连通尝试

本文承接自跨域请求问题浅解-CSDN博客 后端&#xff1a; //主启动类 SpringBootApplication public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}} //控制类 RestController RequestMapping(&quo…

决策树、ID3决策树(信息熵、信息增益)

目录 一、决策树简介 决策树建立过程 二、ID3决策树 核心思想&#xff1a;决策树算法通过计算​​信息增益​​来选择最佳分裂特征 1、信息熵 2、信息熵的计算方法 3、信息增益 4、信息增益的计算&#xff08;难点&#xff09; 5、ID3决策树构建案例 三、总结 一、决策树简介 决…