XingYun blog
  • JS基础

    • 图解js原型链
    • JS Event Loop
    • 对象的底层数据结构
    • 让你的JavaScript代码简单又高效
    • 函数参数按值传递
    • 判断数据类型
    • 浮点数精度问题和解决办法
    • 常用方法snippet
    • 实现Promise
    • 防抖和节流
    • 巧用sort排序
  • CSS && HTML

    • CSS也需要性能优化
    • class命名规范
    • em、px、rem、vh、vw 区别
    • CSS揭秘阅读笔记
  • 浏览器

    • 浏览器是如何渲染页面的
    • 重排和重绘
    • BOM浏览器对象模型
    • DOM事件
    • 浏览器存储
  • 数据结构

    • JS实现链表
    • JS实现栈与栈应用
    • JS实现常见排序
    • 哈夫曼编码
    • MD5算法
  • vue原理浅析

    • Vue虚拟dom与Diff算法
    • 前端打包文件的缓存机制
    • vue数组为什么不是响应式
    • v-for为什么不能用index做key
  • 前端工程化

    • 浏览器是如何渲染页面的
    • 前端打包需要gzip压缩吗
    • 前端打包文件的缓存机制
    • webpack loader和plugin
  • 轮子&&组件库

    • 实现水波浪进度球
  • 文字转语音mp3文件
  • 文件上传前后端实现
  • moment.js给定时间获取自然月、周的时间轴
  • 实现文件上传功能
  • 批量下载照片
  • leaflet改变坐标原点
  • 网络

    • 有了MAC地址 为什么还需要IP地址
    • 为什么IP地址老是变
    • 我们为什么需要IPV6
    • TCP与UDP
  • 计算机组成原理

    • ASCII、Unicode、UTF-8和UTF-16
  • VSCode

    • VSCode图片预览插件 Image preview
    • rsync:linux间的高效传输工具

XingYun

冲!
  • JS基础

    • 图解js原型链
    • JS Event Loop
    • 对象的底层数据结构
    • 让你的JavaScript代码简单又高效
    • 函数参数按值传递
    • 判断数据类型
    • 浮点数精度问题和解决办法
    • 常用方法snippet
    • 实现Promise
    • 防抖和节流
    • 巧用sort排序
  • CSS && HTML

    • CSS也需要性能优化
    • class命名规范
    • em、px、rem、vh、vw 区别
    • CSS揭秘阅读笔记
  • 浏览器

    • 浏览器是如何渲染页面的
    • 重排和重绘
    • BOM浏览器对象模型
    • DOM事件
    • 浏览器存储
  • 数据结构

    • JS实现链表
    • JS实现栈与栈应用
    • JS实现常见排序
    • 哈夫曼编码
    • MD5算法
  • vue原理浅析

    • Vue虚拟dom与Diff算法
    • 前端打包文件的缓存机制
    • vue数组为什么不是响应式
    • v-for为什么不能用index做key
  • 前端工程化

    • 浏览器是如何渲染页面的
    • 前端打包需要gzip压缩吗
    • 前端打包文件的缓存机制
    • webpack loader和plugin
  • 轮子&&组件库

    • 实现水波浪进度球
  • 文字转语音mp3文件
  • 文件上传前后端实现
  • moment.js给定时间获取自然月、周的时间轴
  • 实现文件上传功能
  • 批量下载照片
  • leaflet改变坐标原点
  • 网络

    • 有了MAC地址 为什么还需要IP地址
    • 为什么IP地址老是变
    • 我们为什么需要IPV6
    • TCP与UDP
  • 计算机组成原理

    • ASCII、Unicode、UTF-8和UTF-16
  • VSCode

    • VSCode图片预览插件 Image preview
    • rsync:linux间的高效传输工具
  • leaflet改变坐标原点
  • 补间动画gsap与tween
  • 文字转语音mp3文件
  • JavaScript引入
  • JavaScript高级程序设计阅读笔记
  • Javascript函数参数按值传递传递
  • JS防抖和节流
  • 手写JS常用方法
  • 手写Promise
  • JS Event Loop
  • 重排和重绘
  • em、px、rem、vh、vw 区别
  • css也需要性能优化
  • 图解 js 原型链
  • js函数参数按值传递
  • BOM浏览器对象模型
  • DOM
  • 事件
  • js对象数组sort按需排序
  • 文件上传功能技术选型和前后端实现
  • 前端图片处理
  • 让你的JavaScript代码简单又高效
  • BEM:class命名规范
  • 前端规范-CSS属性那么多(杂),怎么排序
  • TypeScript Tips
  • jsx
  • canvas基础
  • 前端日志
  • 浏览器存储
  • CSS世界阅读笔记
  • CSS揭秘阅读笔记
  • js变量命名常用规范词
  • 你不知道的JavaScript阅读笔记
  • js对象的底层数据结构
  • js判断数据类型
  • JS浮点数精度问题和解决办法
  • js作用域
  • js堆栈溢出和内存泄漏
  • 浏览器是如何渲染页面的
  • 疑难杂症和踩坑问题合集
  • 免费在线API收集
  • 原生JS实现Ajax请求
  • cookie、session、localStorage、sessionStorage的区别
  • Sass与Less
  • arrayBuffer、blob、file对象
  • TypeScript基础
  • 前端
XingYun
2022-12-12
目录

前端分片计算大文件md5

公司运维项目有个需求: 上传一个大文件包(大概 3GB), 为了保证包的完整性, 需要前端计算 md5 后随文件一起上传

# 什么是 md5

md5 全称: Message-Digest Algorithm 5(信息-摘要算法)

从名字来看就知道它是从 MD3、MD4 发展而来的一种加密算法,其主要通过采集文件的信息摘要,以此进行计算并加密。通过 MD5 算法进行加密,文件就可以获得一个唯一的 MD5 值,这个值是独一无二的,就像我们的指纹一样,因此我们就可以通过文件的 MD5 值来确定文件是否正确,密码进行加密后也会生成 MD5 值,论坛就是通过 MD5 值来验证用户的密码是否正确的。

MD5 是输入 不定长度 信息,输出 固定长度 128-bits 的算法, 一般是以 16 进制输出, 所以计算结果是 32 位 16 进制数

例: 8580f12e027c2d30885b7bba675fe1c6

# 计算原理

  1. 把消息分为 n 个分组
  2. 对最后一个消息分组进行填充
  3. 和输入量进行运算,运算结果位下一个分组的输入量
  4. 输出最终结果

JS 实现例子: 插件 js-spark-md5 (opens new window)

# 前端实现大文件 md5 计算

首先需要明确的点是: 前端不可能一次性读取 3GB 的文件直接用于计算(内存会原地爆炸)

所以这里需要用到分片计算:

引用 js-spark-md5 插件代码如下:

<html>
  <input type="file" id="file" />
  <script src="./spark-md5.min.js"></script>
  <script>
    document.getElementById('file').addEventListener('change', function () {
      var blobSlice =
          File.prototype.slice ||
          File.prototype.mozSlice ||
          File.prototype.webkitSlice,
        file = this.files[0],
        chunkSize = 104857600, // Read in chunks of 100MB
        chunks = Math.ceil(file.size / chunkSize),
        currentChunk = 0,
        spark = new SparkMD5.ArrayBuffer(),
        fileReader = new FileReader()
      console.time('md5计算耗时:')
      console.log(file)

      var temp = file.size / (1024 * 1024)
      console.log(file.name)
      console.log('文件大小:  ' + temp.toFixed(2) + 'MB')
      fileReader.onload = function (e) {
        console.log('read chunk nr', currentChunk + 1, 'of', chunks)
        spark.append(e.target.result) // Append array buffer
        currentChunk++

        if (currentChunk < chunks) {
          loadNext()
        } else {
          console.timeEnd('md5计算耗时:')
          console.log('finished loading')
          console.info('computed hash', spark.end()) // Compute hash
        }
      }

      fileReader.onerror = function () {
        console.warn('oops, something went wrong.')
      }

      function loadNext() {
        var start = currentChunk * chunkSize,
          end = start + chunkSize >= file.size ? file.size : start + chunkSize

        fileReader.readAsArrayBuffer(blobSlice.call(file, start, end))
      }

      loadNext()
    })
  </script>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

以上代码运行可以看到 2.2GB 的文件计算耗时 24 秒左右

上次更新: 2023/04/05, 09:41:10
最近更新
01
JavaScript-test
07-20
02
二维码的原理
07-20
03
利用ChatGPT优化代码
07-20
更多文章>
Theme by Vdoing | Copyright © 2021-2023 XingYun | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式