首页 > 其他分享 >5分钟带你回顾大文件分片以及异步计算hash的步骤

5分钟带你回顾大文件分片以及异步计算hash的步骤

时间:2023-09-01 17:24:17浏览次数:57  
标签:异步 const index chunk file 分片 hash percentage

背景

   文件上传功能在中后台项目中是最常见的功能,分片上传是一种将大文件分割成多个小片段进行上传的技术,可以有效提高文件上传的速度和稳定性。

思路

   1.首先就是使用File.slice对文件进行分割产出一个数组用于存储每个小的chunk片段

   2.异步计算hash值,可用作标识文件进而实现文件的断点续传、秒传等功能,这里我们采用spark-MD5计算文件hash值

   3.在计算hash的时候,特别是文件比较大的时候就会明显感觉应用卡顿,所以采用webworker的方式另外开一个线程去计算文件hash值

 

实现

   本文基于vue作简单实现

1.简单布局-主要是一个input标签,加上用于展示当前计算hash值的进度。

<template>
  <div>
    <div>
      <input
        @change="handleChange"
        ref="inputRef"
        type="file"
      />选择文件
    </div>
    当前计算hash百分比进度<h1 style="color:#fff">{{ precentageRef }}%</h1>
  </div>
</template>

2.创建切片功能函数

const createFileChunk = (file, size = 1024 * 20) => { //可根据传入尺寸确定单个chunk大小
  const chunk = [];
  for (let i = 0; i < file.size; i += size) {
    chunk.push(file.slice(i, i + size));
  }
  return chunk;
};

3.创建hash读取函数

const createHash = async (file) => { //采用异步读取,主要将file传给worker读取
  return new Promise((resolve) => {
    const myWorker = new Worker(); // 创建worker
    myWorker.postMessage({ file });//将要读取hash的文件传给worker
    myWorker.onmessage = (e) => {//读取的过程,用onmessage监听,可以设置读取进度百分比
      const {percentage,hash}=e.data
      precentageRef.value=percentage//将百分比实时展示
      if(percentage>=100){//如果到了100%代表已经读取完毕,就resolve出去
        resolve(hash)
      }
    }; 
  });
};

4.创建worker读取文件hash

import SparkMD5 from 'spark-md5'
 let percentage = 0;//初始化百分比
self.onmessage = (e) => {
  const { file } = e.data;//拿到传过来的文件
  const spark = new SparkMD5();
  function _read(index) {//index为读取的文件chunk下标
    let fileReader = new FileReader();//创建fileReader对文件chunk进行数据读写,并将内容拿给sparkMD5计算hash
    fileReader.readAsArrayBuffer(file[index]);
    fileReader.onload = (e) => {
      spark.append(e.target.result)
      if (index >= file.length-1) {//如果读取完毕就向外发送读取完毕消息
        self.postMessage({
          hash: spark.end(),
          percentage:100
        });
      } else {//否则递归读取下一个chunk
        percentage+=100/file.length
        self.postMessage({ 
          hash: 'pending',
          percentage:percentage
        });
        _read(index + 1);
      }
    };
  }
  _read(0);
};

  

这就是文件分片以及异步计算hash的简化流程。

完整代码:

fileLoader.vue

<template>
  <div>
    <div>
      <input
        @change="handleChange"
        ref="inputRef"
        type="file"
      />选择文件
    </div>
    当前计算hash百分比进度<h1 style="color:#fff">{{ precentageRef }}%</h1>
  </div>
</template>

<script setup>
import Worker from '../worker.js?worker'
import {ref} from 'vue'
const precentageRef=ref(0)
const handleChange = async (e) => {
  const { files } = e.target;
  if(!files)return
  let c = createFileChunk(files[0],1024*1024);

  const hash = await createHash(c);
  if (hash) {
    console.log(c, hash);
  }
};
const handleClick=()=>{
  alert(1)
}
const createFileChunk = (file, size = 1024 * 20) => {
  const chunk = [];
  for (let i = 0; i < file.size; i += size) {
    chunk.push(file.slice(i, i + size));
  }
  return chunk;
};

const createHash = async (file) => {
  return new Promise((resolve) => {
    const myWorker = new Worker(); // 创建worker
    myWorker.postMessage({ file });
    myWorker.onmessage = (e) => {
      console.log(e.data);
      const {percentage,hash}=e.data
      precentageRef.value=percentage
      if(percentage>=100){
        resolve(hash)
      }
    }; // Greeting from Worker.js,worker线程发送的消息
  });
};
</script>

<style lang="scss" scoped></style>

  

worker.js

import SparkMD5 from 'spark-md5'
 let percentage = 0;
self.onmessage = (e) => {
  const { file } = e.data;
  const spark = new SparkMD5();
  function _read(index) {
    let fileReader = new FileReader();
    console.log(index,file.length,file,file[index])
    fileReader.readAsArrayBuffer(file[index]);
    fileReader.onload = (e) => {
      spark.append(e.target.result);

      if (index >= file.length-1) {
        self.postMessage({
          hash: spark.end(),
          percentage:100
        });
      } else {
        percentage+=100/file.length
        self.postMessage({
          hash: 'pending',
          percentage:percentage.toFixed(2)
        });
        _read(index + 1);
      }
    };
  }
  _read(0);
};

  

效果:UI界面比较low!!!

 

  

  

  

标签:异步,const,index,chunk,file,分片,hash,percentage
From: https://www.cnblogs.com/micbin/p/17672435.html

相关文章

  • 重写equals为什么还要重写hashcode
    重写equals为什么还要重写hashcode1、为了保证一个原则,equals相同的两个对象hashcode必须相同。如果重写了equals而没有重写hashcode,会出现equals相同hashcode不相同这个现象。2、在散列集合中,是使用hashcode来计算key应存储在hash表的索引,如果重写了equals而没有重写hashcode,......
  • hashcat 详细命令及使用
    一、常用-m,—hash-type=NUM哈希类别,其NUM值参考其帮助信息下面的哈希类别值,其值为数字。如果不指定m值则默认指md5,例如-m1800是sha512Linux加密。-a,–attack-mode=NUM攻击模式,其值参考后面对参数。“-a0”字典攻击,“-a1”组合攻击;“-a3”掩码攻击。-V......
  • 有序map linkedhashmap
    linkedHashMap中的元素会按照put()进去的顺序进行排序第一个put进去的元素就会放在第一位,以此类推原因是因为:linkedhashmap中维护的是数组与双向链表,第一个值会指向第二个值,第二个又指向第三个,所以就有序了linkedhashmap中有一个特点,可以删除不经常访问(get(key)方法)的元素,不经长......
  • hashmap与hashtable,arraylist与vector
    hashmap:key可以为null,key为null的话,就不会计算hashcode码,直接给了一个0,hashmap是2倍扩容原来的容量左移一位,线程不安全,计算下标不同,hashmap下标是高位与地位的‘&’运算hashtable:key以及value都不能为null,value为null会抛异常,hashcode值是根据key来计算的,而null没有hashcode......
  • HashMap 源码分析
    HashMap简介HashMap主要用来存放键值对,它基于哈希表的Map接口实现,是常用的Java集合之一,是非线程安全的。HashMap可以存储null的key和value,但null作为键只能有一个,null作为值可以有多个JDK1.8之前HashMap由数组+链表组成的,数组是HashMap的主体,链表则是主......
  • C# 将异步改成同步方法
    再此做个记录。最近项目满篇都是async异步方式写代码,但是有些场景并没有执行的异步方法,就是说不需要执行awaitasync。如果要改成同步的方法,需要去掉async,再写个重构同步方法(这个就很积累)如果想不改变async方式,还能有效的执行同步方法。可以加入下面的代码:awaitTask.CompletedTa......
  • 初识MQ-异步通讯的优缺点
          ......
  • qt使用QMetaObject::invokeMethod异步调用或QTimer::singleShot解决很久才能显示界面
    https://blog.csdn.net/weixin_43935474/article/details/124922897//Load();//QMetaObject::invokeMethod(this,"Load",Qt::QueuedConnection);//无参数,QueuedConnection表示异步调用,等主线程QMetaObject::invokeMethod(this,"Load",Qt::QueuedConnectio......
  • HashMap链表树化究竟是怎样的?
    网上一直看到两种说法:1.数组长度大于64且当链表长度>8时,链表转换为红黑树;2.数组长度大于64且当链表长度≥8时,链表转换为红黑树。 上源码,主要是putVal()函数/***ImplementsMap.putandrelatedmethods.**@paramhashhashforkey*@paramkeythekey*@par......
  • 双缓冲异步日志(Async Logging)
    文章目录一、日志系统简介二、功能需求三、性能需求四、高效的异步日志1、异步日志的概念2、双缓冲异步日志解析3、AsyncLogging源码4、代码运行图示五、双缓冲异步日志的相关问题一、日志系统简介日志通常用于故障诊断和追踪(trace),也可用于性能分析。日志通常是分布式系统中事......