前端 JS 经典:大文件分片

简介: 前端 JS 经典:大文件分片

前言:当用户上传大文件的时候,我们需要保证页面的流畅,还要监听上传进度,还有用户如果取消上传后,再度上传相同文件,是否需要从头上传。

1. html 结构

input 按钮,上传文件。会用到 md5 文件 hash 值,方便上传中断后继续上传,如果已经上传的部分,不会重新上传。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta
      name="viewport"
      content="initial-scale=1.0, user-scalable=no, width=device-width"
    />
    <title>document</title>
    <style></style>
  </head>
  <body>
    <input type="file" />
    <script
      src="https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/spark-md5/3.0.2/spark-md5.min.js"
      type="application/javascript"
    ></script>
    <script src="./main.js"></script>
  </body>
</html>

2. main.js

监听 input 按钮,获取到文件,然后传给 cutFile 函数进行分片。返回分片结果。

import { cutFile } from "./cutFile.js";
 
const inputFile = document.querySelector('input[type="file"]');
 
inputFile.onchange = async (e) => {
  const file = e.target.files[0];
  const chunk = await cutFile(file);
  console.log(chunk);
};

3. cutFile.js

切片函数编写,定义 CHUNK_SIZE 每片大小,开启多线程,拿到你电脑内核数。定义 cutFile 方法,传入 file 开始根据内核开始切片。

const CHUNK_SIZE = 1024 * 1024 * 5; // 5MB
const THREAD_COUNT = navigator.hardwareConcurrency || 4; // 拿到内核数
 
export function cutFile(file) {
  return new Promise((resolve) => {
    const chunkCount = Math.ceil(file.size / CHUNK_SIZE);
    const threadChunkCount = Math.ceil(chunkCount / THREAD_COUNT);
    const result = [];
    let finishCount = 0;
 
    for (let i = 0; i < THREAD_COUNT; i++) {
      const worker = new Worker("./worker.js", {
        type: "module",
      });
      let end = (i + 1) * threadChunkCount;
      const start = i * threadChunkCount;
      if (end > chunkCount) {
        end = chunkCount;
      }
      worker.postMessage({
        file,
        CHUNK_SIZE,
        startChunkIndex: start,
        endChunkIndex: end,
      });
      worker.onmessage = (e) => {
        for (let i = start; i < end; i++) {
          result[i] = e.data[i - start];
        }
        worker.terminate();
        finishCount++;
        if (finishCount === THREAD_COUNT) {
          resolve(result);
        }
      };
    }
  });
}

4. worker.js

定义线程切片方法

// worker.js
import { createChunk } from "./createChunk.js";
 
onmessage = async (e) => {
  const {
    file,
    CHUNK_SIZE,
    startChunkIndex: start,
    endChunkIndex: end,
  } = e.target;
 
  const proms = [];
  for (let i = start; i < end; i++) {
    proms.push(createChunk(file, i, CHUNK_SIZE));
  }
  const chunks = await Promise.all(proms);
  postMessage(chunks);
};

5. createChunk.js

给每个分片通过 md5 编码设置一个 hash,判断是否已经上传。

import SparkMD5 from "./sparkmd5.js";
 
export function createChunk(file, index, chunkSize) {
  return new Promise((resolve) => {
    const start = index * chunkSize;
    const end = start + chunkSize;
    const spark = new SparkMD5.ArrayBuffer();
    const fileReader = new FileReader();
    const blob = file.slice(start, end);
 
    fileReader.onload = (e) => {
      spark.append(e.target.result);
      resolve({
        start,
        end,
        index,
        hash: spark.end(),
        blob,
      });
    };
 
    fileReader.readAsArrayBuffer(blob);
  });
}
目录
相关文章
|
10月前
|
Web App开发 存储 数据处理
Chrome 下载大文件报错!用 Streamsaver.js 完美填坑
本文探讨了Chrome下载大文件报“网络错误”的原因及解决方案。由于Chrome对Blob数据有大小限制,导致大文件下载失败。通过将responseType改为ArrayBuffer可临时解决1-2G文件问题,但超3G仍会崩溃。最佳方案是使用Streamsaver.js实现流式下载,边接收边保存,避免内存溢出,完美支持超大文件下载。
5260 3
|
JavaScript 前端开发 API
|
编解码 JavaScript 前端开发
如何在网页播放英文的m3u8文件(基于Javascript搭建的在线网页工具)
什么是m3u8?又该如何在网页中高效、便捷地播放英文的m3u8文件呢?今天这篇文章就带你一起了解,并推荐一种基于Javascript搭建的在线网页工具,让你轻松解决播放问题。
3694 0
|
前端开发 JavaScript 数据可视化
58K star!这个让网页动起来的JS库,前端工程师直呼真香!
Anime.js 是一款轻量级但功能强大的JavaScript动画引擎,它能够以最简单的方式为网页元素添加令人惊艳的动效。这个项目在GitHub上已经获得58,000+星标,被广泛应用于电商页面、数据可视化、游戏开发等场景。
803 8
|
JavaScript 前端开发 容器
|
JavaScript 前端开发
|
存储 JavaScript 前端开发
|
移动开发 JavaScript 前端开发
|
存储 JavaScript 前端开发
|
JavaScript 前端开发

热门文章

最新文章

  • 1
    前端如何存储数据:Cookie、LocalStorage 与 SessionStorage 全面解析
    1318
  • 2
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(九):强势分析Animation动画各类参数;从播放时间、播放方式、播放次数、播放方向、播放状态等多个方面,完全了解CSS3 Animation
    599
  • 3
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(八):学习transition过渡属性;本文学习property模拟、duration过渡时间指定、delay时间延迟 等多个参数
    462
  • 4
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(七):学习ransform属性;本文学习 rotate旋转、scale缩放、skew扭曲、tanslate移动、matrix矩阵 多个参数
    462
  • 5
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(六):全方面分析css的Flex布局,从纵、横两个坐标开始进行居中、两端等元素分布模式;刨析元素间隔、排序模式等
    582
  • 6
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(五):背景属性;float浮动和position定位;详细分析相对、绝对、固定三种定位方式;使用浮动并清除浮动副作用
    760
  • 7
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(四):元素盒子模型;详细分析边框属性、盒子外边距
    1490
  • 8
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(三):元素继承关系、层叠样式规则、字体属性、文本属性;针对字体和文本作样式修改
    334
  • 9
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(二):CSS伪类:UI伪类、结构化伪类;通过伪类获得子元素的第n个元素;创建一个伪元素展示在页面中;获得最后一个元素;处理聚焦元素的样式
    1205
  • 10
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(一):CSS发展史;CSS样式表的引入;CSS选择器使用,附带案例介绍
    545