前端实现大文件分片上传

前端实现大文件分片上传

背景说明

如果太大的文件,比如:一个视频(2G),一般的文件上传方法可能会出链接现超时的情况,而且也会超过服务端允许上传文件的大小限制,所以解决这个问题我们可以将文件进行分片上传,每次只上传很小的一部分(2M)。

Blob 它表示原始数据, 也就是二进制数据,同时提供了对数据截取的方法 slice,而 File 继承了 Blob 的功能,所以可以直接使用此方法对数据进行分段处理。

过程分析

把大文件进行分段(2M),发送到服务器的同时,携带一个标志(当前的时间戳),用于标识一个完整的文件。

  • 服务端保存各段文件
  • 客户端所有文件分片上传完成之后,发送给服务端一个合并文件的请求
  • 服务端根据文件标识、类型、各分片顺序进行文件合并
  • 删除分片文件

前端JS代码

function upload() {
  // 分片大小设置为 2MB
  var chunkSize = 2097152;
  // 获取选择的文件
  var file = document.getElementById('f1').files[0];
  // 存放文件分片的数组
  var chunks = [];
  // 使用当前时间戳作为上传标识符(token)
  var token = new Date().getTime();
  // 获取文件名
  var name = file.name; 
  // 用来记录文件分片的数量
  var chunkCount = 0; 
  // 用来记录已经上传的分片数量
  var sendChunkCount = 0;
  // 如果文件大小大于分片大小
  if (file.size > chunkSize) {
    var start = 0, end = 0;
    while (true) {
      // 每次将end增加一个分片大小
      end += chunkSize;
      // 切割文件分片
      var blob = file.slice(start, end);
      // 更新起始位置
      start += chunkSize;
      // 如果没有更多的分片,跳出循环
      if (!blob.size) {
        break;
      }
      // 将分片加入数组
      chunks.push(blob);
    }
  } else {
    // 如果文件较小,则不分片,直接加入
    chunks.push(file.slice(0));
  }
  chunkCount = chunks.length;
  // 遍历所有分片
  for (var i = 0; i < chunkCount; i++) {
    // 创建一个新的 FormData 对象来发送数据
    var fd = new FormData();
    // 添加上传会话标识
    fd.append('token', token);
    // 添加当前分片数据
    fd.append('f1', chunks[i]);
    // 添加当前分片的索引
    fd.append('index', i);
    // 调用上传函数
    xhrSend(fd, function() {
      // 成功上传一个分片,已上传分片数加一
      sendChunkCount += 1;
      // 如果所有分片都上传完毕
      if (sendChunkCount === chunkCount) {
        // 上传完成,发送合并请求
        var formD = new FormData();
        // 标明这是一个合并请求
        formD.append('type', 'merge');
        // 上传会话标识
        formD.append('token', token);
        // 分片数量
        formD.append('chunkCount', chunkCount);
        // 文件名
        formD.append('filename', name);
        // 发送合并请求
        xhrSend(formD);
      }
    });
  }
}
function xhrSend(fd, cb) {
  var xhr = new XMLHttpRequest();
  xhr.open('POST', 'http://localhost:8100/', true);
  // 请求状态变化时触发的回调
  xhr.onreadystatechange = function() {
    console.log('状态变化', xhr.readyState);
    if (xhr.readyState == 4) {
      console.log("打印服务器响应", xhr.responseText);
      // 如果回调函数存在,调用它
      cb && cb();
    }
  }
  xhr.send(fd);
}
 
//绑定提交事件
document.getElementById('btn-submit').addEventListener('click',submitUpload);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值