返回

React + Node 大文件分片上传、断点续传、秒传思路

前端

随着互联网的发展,越来越多的数据需要在网上进行传输,其中就包括大文件。例如,视频、音频、图像和软件安装包等,这些文件动辄几十兆、上百兆,甚至上千兆。如果使用传统的上传方式,很容易造成网络拥塞,影响其他用户的正常使用。因此,我们需要一种新的方式来解决大文件上传的问题。

分片上传是一种常见的大文件上传技术。它的基本原理是将大文件切分成更小的块,然后将这些小块分别上传到服务器。服务器收到小块后,再将它们组装成完整的文件。这种方法可以有效地提高上传速度,并减少网络拥塞。

React 是一个流行的前端框架,它可以用来构建各种各样的 Web 应用。Node.js 是一个跨平台的 JavaScript 运行时环境,它可以用来构建各种各样的服务器端应用。本文将介绍如何使用 React + Node.js 实现大文件分片上传、断点续传和秒传。

React + Node 大文件分片上传、断点续传、秒传思路

整体思路

  1. 将文件切成多个小的文件;
  2. 将切片并行上传;
  3. 所有切片上传完成后,服务器端进行切片合成;
  4. 当分片上传失败,记录下失败的分片,下次继续上传失败的分片。

详细步骤

  1. 前端代码

首先,我们需要在前端代码中实现文件切片的功能。我们可以使用 FileReader API 来读取文件,然后将文件分成更小的块。

const file = document.querySelector('input[type=file]');

file.addEventListener('change', (e) => {
  const reader = new FileReader();

  reader.onload = (e) => {
    const arrayBuffer = e.target.result;
    const chunkSize = 1024 * 1024; // 1MB
    const chunks = [];

    for (let i = 0; i < arrayBuffer.byteLength; i += chunkSize) {
      const chunk = arrayBuffer.slice(i, i + chunkSize);
      chunks.push(chunk);
    }

    // 上传切片
    uploadChunks(chunks);
  };

  reader.readAsArrayBuffer(file.files[0]);
});
  1. Node.js 代码

在 Node.js 代码中,我们需要实现以下功能:

  • 接收前端上传的切片;
  • 将切片保存到本地磁盘;
  • 当所有切片上传完成后,将切片合成完整的文件;
  • 当分片上传失败,记录下失败的分片,下次继续上传失败的分片。
const express = require('express');
const multer = require('multer');
const fs = require('fs');

const app = express();

// 使用 multer 处理文件上传
const upload = multer({ dest: 'uploads/' });

// 上传切片
app.post('/upload-chunk', upload.single('chunk'), (req, res) => {
  const chunkNumber = req.body.chunkNumber;
  const totalChunks = req.body.totalChunks;
  const fileName = req.body.fileName;

  // 将切片保存到本地磁盘
  fs.writeFile(`uploads/${fileName}.part.${chunkNumber}`, req.file.buffer, (err) => {
    if (err) {
      res.status(500).json({ error: err });
      return;
    }

    // 检查是否所有切片都已上传完成
    if (chunkNumber === totalChunks) {
      // 将切片合成完整的文件
      const file = fs.createWriteStream(`uploads/${fileName}`);

      for (let i = 0; i < totalChunks; i++) {
        const chunk = fs.readFileSync(`uploads/${fileName}.part.${i}`);
        file.write(chunk);
      }

      file.end();

      // 删除临时切片文件
      for (let i = 0; i < totalChunks; i++) {
        fs.unlink(`uploads/${fileName}.part.${i}`, (err) => {
          if (err) {
            console.log(err);
          }
        });
      }

      res.status(200).json({ message: '文件上传成功' });
    } else {
      res.status(200).json({ message: '切片上传成功' });
    }
  });
});

// 断点续传
app.post('/resume-upload', upload.single('chunk'), (req, res) => {
  const chunkNumber = req.body.chunkNumber;
  const totalChunks = req.body.totalChunks;
  const fileName = req.body.fileName;

  // 检查切片是否已存在
  fs.exists(`uploads/${fileName}.part.${chunkNumber}`, (exists) => {
    if (exists) {
      res.status(409).json({ error: '该切片已存在' });
      return;
    }

    // 将切片保存到本地磁盘
    fs.writeFile(`uploads/${fileName}.part.${chunkNumber}`, req.file.buffer, (err) => {
      if (err) {
        res.status(500).json({ error: err });
        return;
      }

      res.status(200).json({ message: '切片上传成功' });
    });
  });
});

// 秒传
app.post('/check-file-exist', (req, res) => {
  const fileName = req.body.fileName;

  // 检查文件是否存在
  fs.exists(`uploads/${fileName}`, (exists) => {
    if (exists) {
      res.status(200).json({ exists: true });
    } else {
      res.status(200).json({ exists: false });
    }
  });
});

app.listen(3000);

使用说明

  1. 首先,你需要在前端代码中实现文件切片的功能。
  2. 然后,你需要在 Node.js 代码中实现接收前端上传的切片、将切片保存到本地磁盘、当所有切片上传完成后,将切片合成完整的文件、当分片上传失败,记录下失败的分片,下次继续上传失败的分片的功能。
  3. 最后,你就可以使用 React + Node.js 来实现大文件分片上传、断点续传和秒传的功能了。