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

2024-06-04 7491阅读

1. 文件分块

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

2. 断点续传

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

3. node项目目录初始化

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

  1. 安装依赖

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

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

代码附上

index.html


  
    
    
    Document
  
  
    
    
      // functions
      // 实现切片的方法
      const makeChunk = (file, size = 1024 * 1024 * 4) => {
        const chunks = [];
        for (let i = 0; i  {
        // 1. 使用Promise.all保证所有上传方法执行成功
        // 2. 必须要给每个分片文件加标识,才可以让node端进行按序拼接
        const list = [];
        for (let i = 0; i  {
            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);
      });
    
  

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");
});

最终效果

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

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


    免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

    目录[+]