文件分块+断点续传 实现大文件上传全栈解决方案(前端+nodejs)

1. 文件分块

将大文件切分成较小的片段(通常称为分片或块),然后逐个上传这些分片。这种方法可以提高上传的稳定性,因为如果某个分片上传失败,只需要重新上传该分片而不需要重新上传整个文件。同时,分片上传还可以利用多个网络连接并行上传多个分片,提高上传速度。

2. 断点续传

在上传过程中,如果网络中断或上传被中止,断点续传技术可以记录已成功上传的分片信息,以便在恢复上传时继续上传未完成的部分,而不需要重新上传整个文件。这种技术可以大大减少上传失败的影响,并节省时间和带宽。

3. node项目目录初始化

在这里插入图片描述

  1. 安装依赖

    • express 敏捷启动服务
    • multer 读取文件,存储
    • cors 解决跨域
  2. 目录结构

    • src
      • TED.mp4 (长视频,10分钟,可以下载这个 https://mirror.aarnet.edu.au/pub/TED-talks/911Mothers_2010W-480p.mp4
    • uploads 存放切片
    • video 存放将切片拼接后的视频
    • index.html 前端页面

代码附上

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <input id="file" type="file" />
    <script>
      // functions
      // 实现切片的方法
      const makeChunk = (file, size = 1024 * 1024 * 4) => {
        const chunks = [];
        for (let i = 0; i < file.size; i += size) {
          const chunk = file.slice(i, i + size);
          chunks.push(chunk);
        }
        return chunks;
      };

      // 上传分片后的文件方法
      const uploadChunks = (chunks) => {
        // 1. 使用Promise.all保证所有上传方法执行成功
        // 2. 必须要给每个分片文件加标识,才可以让node端进行按序拼接
        const list = [];
        for (let i = 0; i < chunks.length; i++) {
          const formData = new FormData();
          formData.append("filename", "ted");
          formData.append("index", i);
          formData.append("chunk", chunks[i]); // 千万注意,切片文件要最后append否则会出现意外的bug

          list.push(
            fetch("http://localhost:3000/upload", {
              method: "POST",
              body: formData,
            })
          );
        }

        Promise.all(list)
          .then((res) => {
            console.log("上传成功", res);
            fetch("http://localhost:3000/merge", {
              method: "POST",
              headers: {
                "Content-Type": "application/json",
              },
              body: JSON.stringify({
                fileName: "TED演讲10分钟长视频",
              }),
            });
          })
          .catch((err) => {
            console.error("上传失败", err);
          });
      };

      // logic
      const file = document.querySelector("#file");
      file.addEventListener("change", (e) => {
        let file = e.target.files[0]; // 我们只处理单个文件因此取第一个元素即可
        // file是一个对象,底层继承于Blob,借助于Blob身上的slice方法,可以实现对大文件的分片操作
        console.log(file);
        const chunks = makeChunk(file);
        console.log("chunks:", chunks);
        uploadChunks(chunks);
      });
    </script>
  </body>
</html>

index.js

import fs from "node:fs";
import path from "node:path";
import express from "express";
import multer from "multer";
import cors from "cors";

console.log("cors:", cors);

// 1. 初始化multer
const storage = multer.diskStorage({
  // 指定切片存放目录
  destination: function (req, file, cb) {
    cb(null, "../uploads/");
  },
  filename: function (req, file, cb) {
    console.log("req.body.index:", req.body.index);
    console.log("file", file);
    cb(null, `${req.body.filename}-${req.body.index}`);
  },
});

const upload = multer({ storage });

const app = express();
app.use(cors());
app.use(express.json());

// upload.single("chunk") 其中chunk对应前端上传的文件切片名字
app.post("/upload", upload.single("chunk"), (req, res) => {
  console.log("req.body:", req.body);
  res.header("Content-Type", "application/json;charset=utf-8");
  res.send("ok");
});

// 拼接切片
app.post("/merge", (req, res) => {
  // 获取uploadDir的目录
  const uploadDir = path.join(process.cwd(), "../uploads");
  const dirs = fs.readdirSync(uploadDir); // 发现是乱序的
  // 对dirs数组进行排序
  dirs.sort((a, b) => {
    return a.split("-")[1] - b.split("-")[1];
  });
  const videoDir = path.join(
    process.cwd(),
    "../video",
    `${req.body.fileName}.mp4`
  );

  dirs.forEach((item) => {
    // 合并成一个完整的文件至video目录
    fs.appendFileSync(videoDir, fs.readFileSync(path.join(uploadDir, item)));
    // 删除已合并的切片文件
    fs.unlinkSync(path.join(uploadDir, item));
  });
  console.log(dirs);
  res.send("okk");
});

app.listen(3000, () => {
  console.log("server is running at port 3000");
});

最终效果

在这里插入图片描述
在这里插入图片描述

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

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

相关文章

linux 搭建知识库文档系统 mm-wiki

目录 一、前言 二、常用的知识库文档工具 2.1 PingCode 2.2 语雀 2.3 Tettra 2.4 Zoho Wiki 2.5 Helpjuice 2.6 SlimWiki 2.7 Document360 2.8 MM-Wiki 2.9 其他工具补充 三、MM-Wiki 介绍 3.1 什么是MM-Wiki 3.2 MM-Wiki 特点 四、搭建MM-Wiki前置准备 4.1 前置…

带环链表及例题

环形链表&#xff0c;链表中的尾节点指向链表中的某个节点导致形成循环的链表。 通过图可以这样表示。 我们一般采用快慢指针的方式解决带环链表的题目&#xff0c;下面直接上例题 环形链表 力扣链接&#xff1a; . - 力扣&#xff08;LeetCode&#xff09; 让我们判断一个…

渗透测试之sql注入绕过技巧

在sql注入中&#xff0c;通常会将某些关键的字符过滤掉&#xff0c;以此来达到预防sql注入的目的。这时我们就可以通过某些技巧来绕过。 绕过技巧1&#xff1a; 这个是在某个比赛中出现的&#xff0c;当时并没有多少人成功绕过。 如下&#xff1a; 如下图&#xff1a;在php中…

Django前后端项目部署

Django前后端分离项目部署 本文采用阿里云服务器&#xff0c;centos7.9操作系统 本文默认服务器已安装nginx,mysql并且可以正常运行Django vue uwsgi nginx注意&#xff1a;先部署后端&#xff0c;使用postman测试请求没有问题后在修改vue中的axios文件中baseURL&#xff0…

PLC通过Modbus转Profinet网关连接变频器与电机通讯

Modbus转Profinet网关&#xff08;XD-MDPN100&#xff09;是一种能够实现Modbus协议和Profinet协议之间转换的设备。Modbus转Profinet网关可提供单个或多个RS485接口&#xff0c;PLC作为控制中枢&#xff0c;变频器作为控制电机转速&#xff0c;通过Modbus转Profinet网关&#…

美国站群服务器的定义、功能以及在网站运营中的应用

美国站群服务器的定义、功能以及在网站运营中的应用 在当今互联网的蓬勃发展中&#xff0c;站群服务器已成为网站运营和SEO优化中不可或缺的重要工具之一。尤其是美国站群服务器&#xff0c;在全球范围内备受关注。本文将深入探讨美国站群服务器的定义、功能以及在网站运营中的…

【城市】应届生第一次打工需要知道的常识(薪资结构,社保,五险二金,个税,专项扣除)

【城市】应届生第一次打工需要知道的常识&#xff08;薪资结构&#xff0c;社保&#xff0c;五险二金&#xff0c;个税&#xff0c;专项扣除&#xff09; 文章目录 1、什么是应届生 & 如何界定应届生2、社保&#xff0c;五险一金&#xff0c;五险二金3、薪资结构&#xff0…

运存与内存?内存与存储? 傻傻分不清

主页: 元存储博客 图片来源: Blackblaze 文章目录 名词为何“内存”的含义混乱内存和存储含义内存和存储作用RAM 与 存储差异速度和性能容量和尺寸易失性和持久性常见问题:总结名词 内存: Memory,如内存条 存储器: Storage, 包括硬盘等 为何“内存”的含义混乱 <

class089 贪心经典题目专题1【左程云算法】

class089 贪心经典题目专题1【左程云算法】 前言版权推荐class089 贪心经典题目专题1code1 179. 最大数code2 1029. 两地调度code3 1553. 吃掉 N 个橘子的最少天数code4 253. 会议室IIcode5 630. 课程表 IIIcode6 1167. 连接棒材的最低费用(leetcode测试)code6 P1090 连接棒材的…

C进阶-数据的存储

文章目录 1. 数据类型介绍类型的基本归类 2. 整型在内存中的存储:原码,反码,补码2.1. 原码,反码,补码 2.2. 大小端介绍大端字节序存储小端字节序存储例:设计程序判断是大端还是小端? 2.3. 练习练习1练习2练习3练习4 3. 浮点型在内存中的存储 1. 数据类型介绍 数据类型数据类型…

YARN详解

YARN 简介 YARN 是Yet Another Resource Negotiator的缩写。 YARN是第二代MapReduce,即MRv2,是在第一代MapReduce基础上演变而来的,主要是为了解决原始Hadoop扩展性较差,不支持多计算框架而提出的;通俗讲就是资源管理器. YARN核心思想: 将 MR1 中资源管理和作业调度两个功能分…

node.js 解析post请求 方法二

前提&#xff1a;以前面发的node.js解析post请求方法一为模板&#xff0c;具体见 http://t.csdnimg.cn/ABaIn 此文我们运用第二种方法&#xff1a;使用第三方模块formidable对post请求进行解析。 1》代码难点 *** 在Node.js中使用formidable模块来解析POST请求主要涉及到处理…

读(用知云翻译)gaitedge论文

文章目录 前言摘要一、介绍二、相关工作2.1步态识别2.2端到端学习 三、跨域问题四、我们的框架4.1步法合成4.2步态对准模块 五、实验5.1设置5.2性能比较5.3消融实验5.4可视化 六、结论 前言 本篇博客仅为个人学习&#xff0c;全文均为知云翻译&#xff0c;如有翻译不当&#x…

Android中的屏幕刷新机制(动画视频形象说明机制)

一&#xff0c;刷新率和帧率&#xff0c;60hz和60fps的区别 在Android系统中&#xff0c;刷新率和帧率是两个不同的概念&#xff0c;它们各自在显示过程中扮演着不同的角色。以下是对它们的详细解释&#xff1a; 刷新率&#xff0c;单位是Hz&#xff0c;是指屏幕在一秒内刷新…

Python来计算 1,2,3,4 能组成多少个不相同且不重复的三位数?

我们今天的例子是 有 1&#xff0c;2&#xff0c;3&#xff0c;4 四个数字&#xff0c;它们能组成多省个互不相同且无重复的三位数&#xff1f;都分别是多少&#xff1f; 话不多说&#xff0c;我们先上代码 num 0 # 我们写了三个for循环&#xff0c;表示生成的三位数 for i…

ROS 2边学边练(41)-- 使用基于tf2_ros::MessageFilter带标记(位姿、时间...)的数据类型

前言 此篇将介绍如何利用tf2来使用传感器数据&#xff08;如单声道和立体声摄像机以及雷达&#xff09;。 假设我们创建了一只海龟叫turtle3&#xff0c;它的里程计不大好用&#xff0c;为了监视turtle3的活动轨迹&#xff0c;有台头顶摄像机被安装到该海龟的背上&#xff08;负…

arp欺骗详解

目录 arp攻击原理 arp协议简介 arp攻击原理 arp实验 实验环境 实验步骤 1、使用ipconfig命令查看靶机&#xff08;window10&#xff09;的IP地址为下一步攻击做好准备&#xff0c;这一步是模拟你获取对方IP的过程 2、使用ifconfig查询查看攻击者&#xff08;kali&#x…

【华为 ICT HCIA eNSP 习题汇总】——题目集19

1、&#xff08;多选&#xff09;以下选项中&#xff0c;FTP 常用文件传输类型有&#xff08;&#xff09;。 A、ASCII 码类型 B、二进制类型 C、EBCDIC 类型 D、本地类型 考点&#xff1a;应用层 解析&#xff1a;&#xff08;AB&#xff09; 文件传输协议&#xff08;FTP&…

Win10无法合并分区?尝试以下2种解决方法吧

若Win10无法合并分区&#xff0c;导致C盘无法扩容&#xff0c;该如何解决呢&#xff1f;本文将介绍如何利用磁盘管理工具和傲梅分区助手轻松解决这个问题&#xff01; 为什么要合并硬盘分区&#xff1f; 合并硬盘分区是指将同一硬盘上的两个分区合并成一个&#xff0c;或者将…

K8S controller编写之Informer的原理+使用[drift]

概念 核心思想&#xff08;重点&#xff09;watch-list 机制 Watch 通过 HTTP 协议与 Kubernetes API Server 建立长连接&#xff0c;接收 Kubernetes API Server 发来的资源变更事件。Watch 操作的实现机制使用 HTTP 协议的分块传输编码——当 client-go 调用 Kubernetes API…