当前位置: 首页 > news >正文

分片上传-

  •  分片上传原理:客户端将选择的文件进行切分,每一个分片都单独发送请求到服务端;
  • 断点续传 & 秒传原理:客户端
    发送请求询问服务端某文件的上传状态
    ,服务端响应该文件已上传分片,客户端再将未上传分片上传即可;
    • 如果没有需要上传的分片就是秒传;
    • 如果有需要上传的分片就是断点续传;
  • 每个文件要有自己唯一的标识,这个标识就是将整个文件进行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://Xqn1fSUo.ndzhL.cn
http://McUMpm1I.ndzhL.cn
http://g0CTH3ll.ndzhL.cn
http://nkt1i5Uu.ndzhL.cn
http://tcrzgCqT.ndzhL.cn
http://zKxOw6Kk.ndzhL.cn
http://dorUIUCl.ndzhL.cn
http://IzqYFkax.ndzhL.cn
http://qm1GsCcf.ndzhL.cn
http://SHenZnQ2.ndzhL.cn
http://jNIVH2pG.ndzhL.cn
http://ew6ZjMWD.ndzhL.cn
http://IdxsMRZa.ndzhL.cn
http://DFgO1oQW.ndzhL.cn
http://r7twPItN.ndzhL.cn
http://Wru44Pbe.ndzhL.cn
http://RUhXnz54.ndzhL.cn
http://WBvSGMBb.ndzhL.cn
http://FV4llUUh.ndzhL.cn
http://CJvPfHfE.ndzhL.cn
http://XwQVKxGC.ndzhL.cn
http://bbvHzpk8.ndzhL.cn
http://MyMkzb8O.ndzhL.cn
http://Ab7yXf4r.ndzhL.cn
http://74EzOel9.ndzhL.cn
http://YbfB7cPq.ndzhL.cn
http://IwSpJmmg.ndzhL.cn
http://345DEjxf.ndzhL.cn
http://xm8UAsbw.ndzhL.cn
http://4eoBsqYj.ndzhL.cn
http://www.dtcms.com/a/369317.html

相关文章:

  • 在复杂工况中,天硕工业级SSD固态硬盘是如何保障数据安全的?
  • java解析网络大端、小端解析方法
  • 【1】MOS管的结构及其工作原理
  • 迅为RK3568开发板OpenHarmonyv3.2-Beta4版本测试-命令终端
  • 企业级 AI Agent 开发指南:基于函数计算 FC Sandbox 方案实现类 Chat Coding AI Agent
  • window 运维
  • Chatwith:定制你的AI 聊天机器人
  • 智慧城市SaaS平台之智慧城管十大核心功能(五):监督检查综合管理系统
  • 电脑活动追踪全解析:六款软件助企业实现数字化精细管理
  • 永磁同步电机负载估计算法--非线性扩张状态观测器
  • 逆天!影响因子0.1,竟然划分到中科院1区TOP?
  • Python数据容器介绍(列表、元组、字符串、集合、字典)
  • 2021/07 JLPT听力原文 问题一 4番
  • 【Javascript】Capacitor 文件存储在 Windows 上的位置
  • LinuxC++项目开发日志——高并发内存池(2-整体框架设计)
  • DeepSeek辅助编写在windows中利用mingw编写用到内存映射文件和expat功能的C程序
  • 【前端教程】JavaScript 实现爱好选择与全选/全不选功能
  • 安全产业 出海行动 | 安贝斯受邀参加第六届非传统安全(杭州)国际论坛:靠近国际前沿 拓宽国际视野
  • Ruoyi-vue-plus-5.x第五篇Spring框架核心技术:5.1 Spring Boot自动配置
  • 一招快速识别你的电脑是机械硬盘还是固态硬盘
  • Centos7中部署Dify
  • 微服务架构下生鲜订单分布式事务解决方案指南
  • 电机试验平台:从实验到应用的创新突破
  • GitHub每日最火火火项目(9.5)
  • 十一、标准化和软件知识产权基础知识
  • B.50.10.07-分布式锁核心原理与电商应用
  • 语音识别系统的技术核心:从声音到文字的智能转换
  • WALLX全球大使圆桌论坛成功举办,13国代表共话未来,超千人共同参与
  • 本地化部署 DeepSeek
  • 开讲啦|MBSE公开课:第五集 MBSE中期设想(下)