文件上传之大文件分块上传

原则:合久必分,分久必合

优势部分:减少了内存占用,可实现断点续传,并发处理,利用带宽,提高效率
不足之处:增加复杂性,增加额外计算存储
应用场景:云存储大文件上传、多媒体平台音视频上传,需断点续传应用
注意事项:合理分块大小,顺序的完整性,异常情况的合理处理

前端

html:

<input type="file" id="fileInput">
<button onclick="upload()">上传文件</button>

script:

async function upload() {
    const fileInput = document.getElementById('fileInput'); //获取input框
    const file = fileInput.files[0]; // 对input的文件进行获取

    const chunkSize = 1*1024*1024;  //初始化分块的尺寸 每块分块文件大小为1MB(1兆)
    const totalChunks = Math.ceil(file.size / chunkSize); //通过文件尺寸计算出所有的块数
    let currentChunk = 0; //设置块的初始值

    // 通过while循环处理
    while (currentChunk < totalChunks){
        const start = currentChunk * chunkSize;  // 计算当前块的起始位置
        const end = Math.min(start + chunkSize, file.size); // 计算当前块的结束  Math.min:返回一组数值中的最小值
        const chunk = file.slice(start, end); // 切割文件获取当前块

        const formData = new FormData();
        formData.append('file', chunk); // 添加当前块到 FormData 对象
        formData.append('filename', file.name); // 添加文件名到 FormData 对象
        formData.append('totalChunks', totalChunks); // 添加总块数到 FormData 对象
        formData.append('currentChunk', currentChunk); // 添加当前块数到 FormData 对象
    
        try{
            await axios.post('http://localhost:3000/upload',formData,{
                headers:{
                    'Content-Type':'multipart/form-data',
                },
            }); //发送当前块的上传请求
        }catch(error){
            console.error(error);
            return;
        }

        currentChunk++; //增加当前块数,继续下一块的上传(实现循环操作)
    }

    // 当所有分块文件发送完毕,发起合并请求操作
    try{
        const postData = { filename:file.name,totalChunks:totalChunks }; //构造合并请求的数据
        await http.post('http://localhost:3000/merge', postData,{
            headers: {
            'Content-Type': 'application/json'
            }
        }); //发送合并请求
    }catch(error){
        console.error(error);
    }
}

点击上传触发查看

将会向服务器不断发送块级的一个文件内容,将文件以 binary(二进制) 进行数据的传递

后端(服务器端)

进行后端配置:

const express = require('express');
const cors = require('cors');  // 解决跨域问题
const path = require('path');  // 处理路径问题
const fs = require('fs');  // 文件读取操作
const multer = require('multer');  // 进行文件上传的操作处理
const upload = multer({dest:'uploads/'});  // 设置文件上传地址
const bodyParser = require('body-parser'); // 实现body解析操作
const app = express();
 
app.use(cors());
app.use(bodyParser.json());  // 实现中间件body的应用
app.use(bodyParser.urlencoded({extended:false}));  // 实现文件路径的处理
 
app.post('/upload',(req,res) => {});  // 实现文件上传的请求操作
 
app.listen(3000,() => {
    console.log('Server started on port 3000');
});

upload上传接口:

 upload.single('file'):利用 multer 实现单文件上传的操作处理

app.post('/upload',upload.single('file'),(req,res) => {
    const file = req.file; // 获取上传的文件对象
    const filename = req.body.filename; // 获取文件名
    const totalChunks = parseInt(req.body.totalChunks); // 获取总块数
    const currentChunk = parseInt(req.body.currentChunk); //获取当前块数
    const chunkPath = path.join(
        "uploads/",
        `${filename}-chunk-${currentChunk}`
    ); // 设置当前文件的存储路径
 
    const chunkStream = fs.createReadStream(file.path); //创建读取文件块的可读流
    const writeStream = fs.createWriteStream(chunkPath); //创建写入当前块的可写流
 
    chunkStream.pipe(writeStream); //通过chunkStream.pipe管道操作,将读取的文件块内容通过管道写入当前块的文件
 
    // 对分块上传内容结束以后的事件监听
    chunkStream.on("end", () => {
        fs.unlinkSync(file.path); //读取文件块的流结束后,删除临时文件
        res.sendStatus(200); //响应上传成功的状态
    });
});

切片上传之后,在进行合并操作

merge合并接口:

router.post("/merge", (req, res) => {
    const filename = req.body.filename; //获取文件名
    const totalChunks = parseInt(req.body.totalChunks);  //获取总块数
 
    const mergedPath = path.join("uploads", filename); //生成合并后文件的存储路径
    const writeStream = fs.createWriteStream(mergedPath); //创建写入合并后文件的可写流
 
    // 合并文件块
    const mergeChunks = (index) => {
      if (index === totalChunks) {
        writeStream.end(); //所有块都合并完成后,关闭写入流
        res.sendStatus(200); //响应合并成功的状态
        return;
      }
 
      const chunkPath = path.join("uploads", `${filename}-chunk-${index}`); //获取当前块的存储路径
      const chunk = fs.readFileSync(chunkPath); //同步读取当前块的内容
      fs.unlinkSync(chunkPath); //删除已合并的块文件
 
      writeStream.write(chunk,() => {
        mergeChunks(index + 1); //递归合并下一块
      });
    };
 
    mergeChunks(0); //从第一块开始合并
});

点击上传触发查看

后端产生大量的块级文件

并且在结束后合并成一个文件

至此,已经实现了大文件上传分块操作,利用合久必分的原则,前端进行看块级的分割,然后向服务器端不断的发送块级文件内容,以便实现服务器端的分久必合操作

然后客户端利用发送以后的处理,通过merge合并请求的发起,回到服务器端利用merge分久必合以后的内容进行一个请求操作,最终形成的是一个完整的上传文件内容

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

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

相关文章

Springboot的 Lombok全部关联注解以及核心注解@Data详解

目录 工具安装 依赖注入 注解类别 1. Getter / Setter 2. ToString 3. EqualsAndHashCode 4. NoArgsConstructor / RequiredArgsConstructor / AllArgsConstructor 5. Data 示例 注意事项 6. Value 7. Builder 8. Slf4j / Log / Log4j / Log4j2 / XSlf4j 9. NonN…

03.领域驱动设计:了解实体和值对象以及它们的区别

目录 1、概述 2、实体 1.实体的业务形态 2.实体的代码形态 3.实体的运行形态 4.实体的数据库形态 3、值对象 1.值对象的业务形态 2.值对象的代码形态 3.值对象的运行形态 4.值对象的数据库形态 5.值对象的优势和局限 4、实体和值对象的区别 5、总结 1、概述 DDD战…

企业虚拟机服务器中了lockbit3.0勒索病毒怎么办,lockbit3.0勒索病毒解密处理流程

对于企业来说&#xff0c;企业的数据是企业的核心命脉&#xff0c;关乎着企业的生产与运营的所有工作。随着网络技术的不断发展&#xff0c;网络安全威胁也在不断增加。近期&#xff0c;云天数据恢复中心接到了很多企业的求助&#xff0c;企业的虚拟机服务器遭到了lockbit3.0勒…

vue的pinia环境搭建

一、 pinia是什么&#xff1f; Pinia是Vue的新一代轻量级状态管理库&#xff0c;它允许您跨组件/页面共享状态。Pinia由Vue.js官方成员重新设计&#xff0c;旨在提供更直观、更易于学习的状态管理解决方案。 Pinia的主要特点包括&#xff1a; 对Vue2和Vue3提供良好的支持&#…

机器学习之pandas库学习

这里写目录标题 pandas介绍pandas核心数据结构SeriesDataFrameDataFrame的创建列访问列添加列删除行访问行添加行删除数据修改 pandas介绍 pandas是基于NumPy 的一种工具&#xff0c;该工具是为了解决数据分析任务而创建的。Pandas 纳入 了大量库和一些标准的数据模型&#xff…

C#学习(十一)——Array和Collection

一、集合 集合重要且常用 孤立的数据是没有意义的&#xff0c;集合可以作为大量数据的处理&#xff0c;可进行数据的搜索、迭代、添加、删除。 C#中&#xff0c;所有集合都必须实现ICollection接口&#xff08;数组Array除外&#xff09; 集合说明Array数组&#xff0c;固定长…

【Linux】进程间通信概念 | 匿名管道

文章目录 一、什么是进程间通信进程间通信的概念进程间通信的目的进程间通信的分类进程间通信的本质 二、什么是管道三、匿名管道匿名管道的原理✨站在内核角度理解管道✨站在文件描述符角度理解管道 pipe系统调用fork后在父子进程间使用管道通信代码实现 匿名管道的读写规则管…

初识人工智能,一文读懂机器学习之逻辑回归知识文集(7)

&#x1f3c6;作者简介&#xff0c;普修罗双战士&#xff0c;一直追求不断学习和成长&#xff0c;在技术的道路上持续探索和实践。 &#x1f3c6;多年互联网行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f389;欢迎 &#x1f44d;点赞✍评论…

CSS 双色拼接按钮效果

<template><view class="sss"><button> <!-- 按钮 --><view class="span"> 按钮 </view> <!-- 按钮文本 --></button></view></template><script></script><style>body {b…

uniapp微信小程序-input默认字的样式

需要的是这样的 问题 正常是在input框上面写样式就行&#xff0c;但是uniapp不起作用 解决 直接在input上写placeholder-style"color就解决了 <input class"findInput" type"text" placeholder"关键词查询"placeholder-style"co…

Gin 框架之jwt 介绍与基本使用

文章目录 一.JWT 介绍二.JWT认证与session认证的区别2.1 基于session认证流程图2.2 基于jwt认证流程图 三. JWT 的构成3.1 header : 头部3.2 payload : 负载3.2.1 标准中注册的声明 (建议但不强制使用)3.2.2 公共的声明3.2.3 私有的声明3.2.4 定义一个payload 3.3 signatrue : …

一文掌握SpringBoot注解之@Component 知识文集(5)

&#x1f3c6;作者简介&#xff0c;普修罗双战士&#xff0c;一直追求不断学习和成长&#xff0c;在技术的道路上持续探索和实践。 &#x1f3c6;多年互联网行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f389;欢迎 &#x1f44d;点赞✍评论…

操作系统(5)-----操作系统进程相关

目录 一.进程的组成 1.PCB&#xff08;进程控制块&#xff09; 2.程序段与数据段 二.进程的特征 三.进程的状态以及状态的转换 四.进程的组织 1.链接方式 2.索引方式 五.进程控制 六.进程控制相关原语 1.创建原语 2.撤销原语 3.阻塞原语 4.唤醒原语 5.切换原语 …

Spring MVC 请求流程

SpringMVC 请求流程 一、DispatcherServlet 是一个 Servlet二、Spring MVC 的完整请求流程 Spring MVC 框架是基于 Servlet 技术的。以请求为驱动&#xff0c;围绕 Servlet 设计的。Spring MVC 处理用户请求与访问一个 Servlet 是类似的&#xff0c;请求发送给 Servlet&#xf…

5G赋能智慧文旅:科技与文化的完美结合,打造无缝旅游体验,重塑旅游业的未来

一、5G技术&#xff1a;智慧文旅的强大引擎 5G技术的起源可以追溯到2010年&#xff0c;当时世界各国开始意识到4G技术已经达到了瓶颈&#xff0c;无法满足日益增长的移动通信需求。2013年&#xff0c;国际电信联盟&#xff08;ITU&#xff09;成立了5G技术研究组&#xff0c;开…

力扣516. 最长回文子序列

动态规划 思路&#xff1a; 字符串最长回文子序列问题可以转换为原字符串 s 和逆串 s 的最长公共子序列长度问题&#xff0c;具体推断过程可以参考 力扣1312. 让字符串成为回文串的最少插入次数问题变成了求两个字符串最长公共子序列长度问题&#xff0c;具体思路可以参考 力扣…

物联网协议Coap之C#基于Mozi的CoapClient调用解析

目录 前言 一、CoapClient相关类介绍 1、CoapClient类图 2、CoapClient的设计与实现 3、SendMessage解析 二、Client调用分析 1、创建CoapClient对象 2、实际发送请求 3、Server端请求响应 4、控制器寻址 总结 前言 在之前的博客内容中&#xff0c;关于在ASP.Net Co…

《向量数据库指南》——Milvus Cloud 2023 年关键数据

10 倍 - 内存节省 在 2023 年,RAG 模型被广泛认为是向量数据库的最主要应用之一。我们发现,在文档被分割成块之后,一个含有 500 个 Token 的 Chunk(通常 1000 字节)会转换成一个 1536 维的 float32 向量(通常 6000 字节),这意味着向量数据的体积可能会超过原始文档的…

Linux服务器配置与管理(第三次实验)

实验目的及具体要求 目的 1.熟悉Shell 脚本语法 2.掌握创建脚本的方法 3.掌握运行脚本的方法 4.掌握变量及表达式 5.掌握Shell 控制结构 6.掌握Shell 函数 任务 1.显示当前日期时间、执行路径、用户账户及所在的目录位置 2.判断一个文件是不是字符设备文件&#xff0…

Github 2024-01-28 开源项目日报Top10

根据Github Trendings的统计&#xff0c;今日(2024-01-28统计)共有10个项目上榜。根据开发语言中项目的数量&#xff0c;汇总情况如下&#xff1a; 开发语言项目数量Python项目3TypeScript项目2Rust项目1HTML项目1JavaScript项目1Cuda项目1C#项目1非开发语言项目1 Nuxt&#…