前端大文件分片上传

前端大文件分片上传需要将文件切割成若干个片段,然后将每个片段上传到服务器,最终在服务端将所有的片段合并成完整的文件。下面是一个前端大文件分片上传的示例:

  1. 将文件切割成若干个片段。
function splitFile(file, chunkSize) {
  let fileSize = file.size;
  let start = 0;
  let chunkIndex = 0;
  let chunks = [];

  while (start < fileSize) {
    let end = Math.min(fileSize, start + chunkSize);
    let chunk = file.slice(start, end);
    chunks.push({
      index: chunkIndex,
      start: start,
      end: end,
      file: chunk
    });
    chunkIndex++;
    start = end;
  }

  return chunks;
}
  1. 上传每个片段,使用XMLHttpRequest对象上传。
function uploadChunk(url, chunk, callback) {
  let xhr = new XMLHttpRequest();
  xhr.open("POST", url, true);
  let formData = new FormData();
  formData.append("chunkIndex", chunk.index);
  formData.append("start", chunk.start);
  formData.append("end", chunk.end);
  formData.append("file", chunk.file);
  xhr.onload = function() {
    callback(xhr.status === 200);
  };
  xhr.send(formData);
}
  1. 服务端接收片段。
const express = require("express");
const app = express();
const multer = require("multer");

let storage = multer.diskStorage({
  destination: function(req, file, callback) {
    callback(null, "./uploads");
  },
  filename: function(req, file, callback) {
    callback(null, file.originalname + "_" + req.body.chunkIndex);
  }
});

let upload = multer({ storage: storage }).single("file");

app.post("/upload", function(req, res) {
  upload(req, res, function(err) {
    if (err) {
      res.status(500).send({ message: err.message });
    } else {
      res.status(200).send({ message: "Uploaded successfully" });
    }
  });
});

app.listen(8080);
  1. 合并所有片段。
function mergeChunks(url, fileName, chunkCount, callback) {
  let xhr = new XMLHttpRequest();
  xhr.open("GET", url + "?fileName=" + fileName + "&chunkCount=" + chunkCount, true);
  xhr.onload = function() {
    callback(xhr.status === 200);
  };
  xhr.send();
}
  1. 客户端在上传完所有片段后,将所有片段合并成完整的文件。
let chunkSize = 5 * 1024 * 1024; //每个片段5MB

let file = document.getElementById("file").files[0];
let chunkCount = Math.ceil(file.size / chunkSize);
let chunks = splitFile(file, chunkSize);

let uploadedCount = 0;
for (let i = 0; i < chunks.length; i++) {
  const chunk = chunks[i];
  uploadChunk("/upload", chunk, function(success) {
    uploadedCount++;
    if (uploadedCount === chunkCount) {
      mergeChunks("/merge", file.name, chunkCount, function(success) {
        console.log("File upload " + (success ? "completed" : "failed"));
      });
    }
  });
}

注意,以上代码仅供参考,不同浏览器和服务器可能会有不同的兼容性问题,实际应用时需要进行充分测试和优化。

posted @ 2023-05-21 09:18  kitebear  阅读(332)  评论(0编辑  收藏  举报