大文件分片上传

使用react+antd实现大文件上传(Vue同理,切换组件即可)

import { Upload, Button, message } from "antd";
import { UploadOutlined } from "@ant-design/icons";
import { useRef, useState } from "react";
import axios from "axios";
import SparkMD5 from "spark-md5";

function calculateMD5(file) {
  return new Promise((resolve) => {
    const spark = new SparkMD5.ArrayBuffer();
    const fileReader = new FileReader();
    const chunkSize = 2 * 1024 * 1024;
    let currentChunk = 0;

    fileReader.onload = function (e) {
      spark.append(e.target.result);
      currentChunk++;
      if (currentChunk < chunks) {
        loadNext();
      } else {
        const result = spark.end();
        resolve(result);
      }
    };

    function loadNext() {
      const start = currentChunk * chunkSize;
      const end = Math.min(file.size, start + chunkSize);
      const buffer = file.slice(start, end);
      fileReader.readAsArrayBuffer(buffer);
    }

    const chunks = Math.ceil(file.size / chunkSize);
    loadNext();
  });
}

function chunkFile(file, chunkSize) {
  const chunks = Math.ceil(file.size / chunkSize);
  const chunksList = [];
  let currentChunk = 0;

  while (currentChunk < chunks) {
    const start = currentChunk * chunkSize;
    const end = Math.min(file.size, start + chunkSize);
    const chunk = file.slice(start, end);
    chunksList.push(chunk);
    currentChunk++;
  }

  return chunksList;
}

function App() {
  const [uploading, setUploading] = useState(false);
  const chunkRefs = useRef([]);
  const md5Ref = useRef("");

  const handleFileChange = async ({ file }) => {
    setUploading(true);
    const md5 = await calculateMD5(file);
    md5Ref.current = md5;

    // 将文件分片并保存到 reference 对象中
    const chunksList = chunkFile(file, 2 * 1024 * 1024);
    chunkRefs.current = chunksList.map((chunk, index) => {
      const formData = new FormData();
      formData.append("chunk", chunk);
      formData.append("filename", file.name);
      formData.append("total", chunksList.length);
      formData.append("index", index.toString());
      return formData;
    });

    // 上传分片
    const uploadPromises = chunkRefs.current.map((formData) =>
      axios.post("http://localhost:3000/upload", formData)
    );

    try {
      await Promise.all(uploadPromises);
      message.success("文件上传成功!");
    } catch (error) {
      console.error(error);
      message.error("文件上传失败!");
    }

    setUploading(false);
  };

  return (
    <div>
      <Upload
        name="file"
        accept=".jpg,.jpeg,.png,.gif,.zip,.rar,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx"
        multiple={false}
        showUploadList={false}
        beforeUpload={() => false}
        onChange={handleFileChange}
      >
        <Button loading={uploading} icon={<UploadOutlined />}>
          {uploading ? "上传中" : "开始上传"}
        </Button>
      </Upload>
    </div>
  );
}

export default App;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值